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 }); } };