From 08e60b29b31ae87fb6cd079ea5c26422eff3491d Mon Sep 17 00:00:00 2001 From: SukkaW Date: Wed, 31 Aug 2022 16:20:59 +0800 Subject: [PATCH] fix(#40066): preserve error status code for serveStatic --- packages/next/server/next-server.ts | 42 +++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 28021d731f7..6146f889306 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -145,6 +145,41 @@ function getMiddlewareMatcher( return matcher } +/** + * Hardcoded every possible error status code that could be thrown by "serveStatic" method + * This is done by searching "this.error" inside "send" module's source code: + * https://github.com/pillarjs/send/blob/master/index.js + * https://github.com/pillarjs/send/blob/develop/index.js + */ +const POSSIBLE_ERROR_CODE_FROM_SERVE_STATIC = new Set([ + // send module will throw 500 when header is already sent or fs.stat error happens + // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L392 + // Note: we will use Next.js built-in 500 page to handle 500 errors + // 500, + + // send module will throw 404 when file is missing + // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L421 + // Note: we will use Next.js built-in 404 page to handle 404 errors + // 404, + + // send module will throw 403 when redirecting to a directory without enabling directory listing + // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L484 + // Note: Next.js throws a different error (without status code) for directory listing + // 403, + + // send module will throw 400 when fails to normalize the path + // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L520 + 400, + + // send module will throw 412 with conditional GET request + // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L632 + 412, + + // send module will throw 416 when range is not satisfiable + // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L669 + 416, +]) + export default class NextNodeServer extends BaseServer { private imageResponseCache?: ResponseCache @@ -1332,8 +1367,11 @@ export default class NextNodeServer extends BaseServer { const err = error as Error & { code?: string; statusCode?: number } if (err.code === 'ENOENT' || err.statusCode === 404) { this.render404(req, res, parsedUrl) - } else if (err.statusCode === 412) { - res.statusCode = 412 + } else if ( + typeof err.statusCode === 'number' && + POSSIBLE_ERROR_CODE_FROM_SERVE_STATIC.has(err.statusCode) + ) { + res.statusCode = err.statusCode return this.renderError(err, req, res, path) } else { throw err