83 lines
2.7 KiB
TypeScript
83 lines
2.7 KiB
TypeScript
|
|
import { type NextRequest, NextResponse } from "next/server";
|
||
|
|
import { env } from "~/env";
|
||
|
|
import { TOKEN_CONFIG } from "~/server/auth/configs";
|
||
|
|
import { verifyToken } from "~/server/auth/jwt";
|
||
|
|
|
||
|
|
export const apisMiddleware = async (req: NextRequest) => {
|
||
|
|
const { pathname, searchParams } = req.nextUrl;
|
||
|
|
console.log("APIs Middleware triggered for:", pathname);
|
||
|
|
const accessToken = req.cookies.get(
|
||
|
|
TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME,
|
||
|
|
)?.value;
|
||
|
|
if (!accessToken) {
|
||
|
|
return new NextResponse("Unauthorized", { status: 401 });
|
||
|
|
}
|
||
|
|
const payload = await verifyToken(accessToken);
|
||
|
|
if (!payload) {
|
||
|
|
return new NextResponse("Unauthorized", { status: 401 });
|
||
|
|
}
|
||
|
|
// Build the storage API URL correctly
|
||
|
|
const slug = pathname.replace("/storage-api/", "");
|
||
|
|
|
||
|
|
// Preserve existing query params and add token
|
||
|
|
const params = new URLSearchParams(searchParams);
|
||
|
|
params.set("token", env.STORAGE_TOKEN);
|
||
|
|
|
||
|
|
const storageUrl = `${env.STORAGE_URL}/${slug}?${params.toString()}`;
|
||
|
|
|
||
|
|
try {
|
||
|
|
// Forward the request to storage API
|
||
|
|
const headers = new Headers(req.headers);
|
||
|
|
headers.delete("host");
|
||
|
|
headers.delete("cookie");
|
||
|
|
|
||
|
|
const response = await fetch(storageUrl, {
|
||
|
|
method: req.method,
|
||
|
|
headers: headers,
|
||
|
|
body:
|
||
|
|
req.method !== "GET" && req.method !== "HEAD" ? req.body : undefined,
|
||
|
|
// @ts-expect-error - duplex needed for request streaming
|
||
|
|
duplex: "half",
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!response.ok) {
|
||
|
|
console.error("Storage API error:", response.status);
|
||
|
|
return new NextResponse("Storage API error", { status: response.status });
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get response data
|
||
|
|
const data = await response.arrayBuffer();
|
||
|
|
|
||
|
|
// Create response with proper headers
|
||
|
|
const proxyResponse = new NextResponse(data, {
|
||
|
|
status: response.status,
|
||
|
|
statusText: response.statusText,
|
||
|
|
});
|
||
|
|
|
||
|
|
// Copy relevant headers
|
||
|
|
const contentType = response.headers.get("Content-Type");
|
||
|
|
const contentDisposition = response.headers.get("Content-Disposition");
|
||
|
|
const contentLength = response.headers.get("Content-Length");
|
||
|
|
|
||
|
|
if (contentType) proxyResponse.headers.set("Content-Type", contentType);
|
||
|
|
if (contentDisposition)
|
||
|
|
proxyResponse.headers.set("Content-Disposition", contentDisposition);
|
||
|
|
if (contentLength)
|
||
|
|
proxyResponse.headers.set("Content-Length", contentLength);
|
||
|
|
|
||
|
|
// Set CORS headers
|
||
|
|
proxyResponse.headers.set("Access-Control-Allow-Origin", env.BASE_URL);
|
||
|
|
proxyResponse.headers.set("Access-Control-Allow-Credentials", "true");
|
||
|
|
proxyResponse.headers.delete("X-Frame-Options"); // Remove if set by storage API
|
||
|
|
proxyResponse.headers.set(
|
||
|
|
"Content-Security-Policy",
|
||
|
|
"frame-ancestors 'self'",
|
||
|
|
);
|
||
|
|
|
||
|
|
return proxyResponse;
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Storage proxy error:", error);
|
||
|
|
return new NextResponse("Failed to proxy request", { status: 500 });
|
||
|
|
}
|
||
|
|
};
|