diff --git a/packages/next/server/dev/hot-reloader.ts b/packages/next/server/dev/hot-reloader.ts index a04315a4291a..529baa9195f8 100644 --- a/packages/next/server/dev/hot-reloader.ts +++ b/packages/next/server/dev/hot-reloader.ts @@ -17,7 +17,7 @@ import { import { watchCompilers } from '../../build/output' import * as Log from '../../build/output/log' import getBaseWebpackConfig from '../../build/webpack-config' -import { API_ROUTE, APP_DIR_ALIAS } from '../../lib/constants' +import { APP_DIR_ALIAS } from '../../lib/constants' import { recursiveDelete } from '../../lib/recursive-delete' import { BLOCKED_PAGES, @@ -78,9 +78,8 @@ export async function renderScriptError( } function addCorsSupport(req: IncomingMessage, res: ServerResponse) { - const isApiRoute = req.url!.match(API_ROUTE) - // API routes handle their own CORS headers - if (isApiRoute) { + // Only rewrite CORS handling when URL matches a hot-reloader middleware + if (!req.url!.startsWith('/__next')) { return { preflight: false } } diff --git a/test/development/api-cors-with-rewrite/index.test.ts b/test/development/api-cors-with-rewrite/index.test.ts new file mode 100644 index 000000000000..ea76a4235072 --- /dev/null +++ b/test/development/api-cors-with-rewrite/index.test.ts @@ -0,0 +1,45 @@ +import { createNext } from 'e2e-utils' +import { NextInstance } from 'test/lib/next-modes/base' +import { fetchViaHTTP } from 'next-test-utils' + +describe('Rewritten API Requests should pass OPTIONS requests to the api function', () => { + let next: NextInstance + + beforeAll(async () => { + next = await createNext({ + files: { + 'pages/api/some-endpoint.js': ` + export default (req, res) => { + res.end("successfully hit some-endpoint!") + } + `, + }, + nextConfig: { + rewrites: () => + Promise.resolve({ + beforeFiles: [ + // Nextjs by default requires a /api prefix, let's remove that + { + source: '/:path*', + destination: '/api/:path*', + }, + ], + afterFiles: [], + fallback: [], + }), + }, + dependencies: {}, + }) + }) + afterAll(() => next.destroy()) + + it('should pass OPTIONS requests to the api function', async () => { + const res = await fetchViaHTTP(next.url, '/some-endpoint', null, { + method: 'OPTIONS', + headers: { + Origin: 'http://localhost:3000', + }, + }) + expect(await res.text()).toContain('successfully hit some-endpoint!') + }) +})