fix(pdf-compress): bypass middleware body buffering for upload routes
Next.js middleware buffers the entire request body (10MB default limit) before the route handler runs. middlewareClientMaxBodySize experimental flag doesn't work reliably with standalone output. Solution: exclude api/compress-pdf from middleware matcher so the body streams directly to the route handler. Auth check moved to a shared helper (auth-check.ts) called at the start of each route. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { getToken } from "next-auth/jwt";
|
||||
|
||||
/**
|
||||
* Check auth for routes excluded from middleware (large upload routes).
|
||||
* Returns null if authenticated, or a 401 NextResponse if not.
|
||||
*/
|
||||
export async function requireAuth(
|
||||
req: NextRequest,
|
||||
): Promise<NextResponse | null> {
|
||||
// Skip in development
|
||||
if (process.env.NODE_ENV === "development") return null;
|
||||
|
||||
const token = await getToken({
|
||||
req,
|
||||
secret: process.env.NEXTAUTH_SECRET,
|
||||
});
|
||||
|
||||
if (token) return null;
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "Authentication required" },
|
||||
{ status: 401 },
|
||||
);
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
|
||||
import { readFile, unlink } from "fs/promises";
|
||||
import { join } from "path";
|
||||
import { parseMultipartUpload } from "../parse-upload";
|
||||
import { requireAuth } from "../auth-check";
|
||||
|
||||
/**
|
||||
* iLovePDF API integration for PDF compression.
|
||||
@@ -30,6 +31,9 @@ async function cleanup(dir: string) {
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const authError = await requireAuth(req);
|
||||
if (authError) return authError;
|
||||
|
||||
if (!ILOVEPDF_PUBLIC_KEY) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ import { promisify } from "util";
|
||||
import { join } from "path";
|
||||
import { Readable } from "stream";
|
||||
import { parseMultipartUpload } from "../parse-upload";
|
||||
import { requireAuth } from "../auth-check";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
@@ -58,6 +59,9 @@ function streamFileResponse(
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const authError = await requireAuth(req);
|
||||
if (authError) return authError;
|
||||
|
||||
let tmpDir = "";
|
||||
try {
|
||||
const upload = await parseMultipartUpload(req);
|
||||
|
||||
+1
-1
@@ -46,6 +46,6 @@ export const config = {
|
||||
* - /favicon.ico, /robots.txt, /sitemap.xml
|
||||
* - Files with extensions (images, fonts, etc.)
|
||||
*/
|
||||
"/((?!api/auth|api/notifications/digest|auth/signin|_next|favicon\\.ico|robots\\.txt|sitemap\\.xml|.*\\..*).*)",
|
||||
"/((?!api/auth|api/notifications/digest|api/compress-pdf|auth/signin|_next|favicon\\.ico|robots\\.txt|sitemap\\.xml|.*\\..*).*)",
|
||||
],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user