-
SummaryHi all I would like to define CORS to allow any origin for development purposes with Nextjs 13 route handlers. I tried the following options, but they did not work: In the route handler itself: request.headers.set("Access-Control-Allow-Origin", "*");
request.headers.set("Access-Control-Allow-Methods", "POST");
request.headers.set("Access-Control-Allow-Headers", "Content-Type"); In /** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
appDir: true,
async headers() {
return [
{
// matching all API routes
// https://vercel.com/guides/how-to-enable-cors
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: "*" },
{
key: "Access-Control-Allow-Methods",
value: "GET,OPTIONS,PATCH,DELETE,POST,PUT",
},
{
key: "Access-Control-Allow-Headers",
value:
"X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
},
],
},
];
},
},
};
module.exports = nextConfig; Would appreciate any help. Additional informationNo response ExampleNo response |
Beta Was this translation helpful? Give feedback.
Replies: 15 comments 27 replies
-
I'm also attempting to figure this out. One note, you may want to add the headers function outside of the experimental object. |
Beta Was this translation helpful? Give feedback.
-
@L-U-C-K-Y const nextConfig = {
experimental: {
appDir: true,
},
async headers() {
// ...
},
} Route handler modification is not needed. |
Beta Was this translation helpful? Give feedback.
-
Added an example to the docs: export async function GET(request: Request) {
return new Response('Hello, Next.js!', {
status: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}
});
} |
Beta Was this translation helpful? Give feedback.
-
I only got it working with: export async function GET(request: Request) {
...
return cors(
request,
new Response(JSON.stringify(images), {
status: 200,
headers: { "Content-Type": "application/json" },
})
);
}
export async function OPTIONS(request: Request) {
return cors(
request,
new Response(null, {
status: 204,
})
);
} The |
Beta Was this translation helpful? Give feedback.
-
Middleware approach did not work for me but this worked export const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
};
export async function OPTIONS(req: NextRequest) {
return NextResponse.json({}, { headers: corsHeaders });
}
export async function POST(req: NextRequest) {
// ...
return NextResponse.json({ foo: "bar" }, { headers: corsHeaders });
} |
Beta Was this translation helpful? Give feedback.
-
I have had no issues when adding const getCorsHeaders = () => {
const headers = {};
headers["Access-Control-Allow-Origin"] = "http://localhost:1420";
headers["Access-Control-Allow-Credentials"] = "true";
headers["Access-Control-Allow-Methods"] =
"GET,OPTIONS,PATCH,DELETE,POST,PUT";
headers["Access-Control-Allow-Headers"] =
"X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, Authorization";
return Object.entries(headers).map(([key, value]) => ({ key, value }));
};
const nextConfig = {
reactStrictMode: true,
experimental: {
serverActions: true,
},
headers: async () => {
return [
{
source: "/api/(.*)",
headers: getCorsHeaders(),
},
];
},
swcMinify: true,
};
module.exports = withBundleAnalyzer(nextConfig); |
Beta Was this translation helpful? Give feedback.
-
@leerob I tried your solution and it has gotten rid of my cors errors, however I am trying to only have it work with one of my api routes and I want to specify the allowed origin, however, it seems to be working for all origins. Down below is my next.config /** @type {import('next').NextConfig} */
const nextConfig = {};
module.exports = {
experimental: {
serverActions: true,
},
async headers() {
return [
{
source: "/api/stripe/test",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "false" },
{
key: "Access-Control-Allow-Origin",
value: "https://www.google.com/",
},
{
key: "Access-Control-Allow-Methods",
value: "GET,DELETE,PATCH,POST,PUT",
},
{
key: "Access-Control-Allow-Headers",
value: "Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date",
},
],
},
];
},
}; As you can see I am trying to allow my stripe/test route on the domain google.com.(This is only for testing and I will change it to an actual domain once I have it where I want it) Here is my get request inside /api/stripe/test export async function GET(request: Request) {
const origin = request.headers.get("origin");
console.log("origin", origin);
return new Response("Hello, Next.js!", {
status: 200,
headers: {
"Access-Control-Allow-Origin": origin,
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
});
// return NextResponse.json(message);
} Now that I have added this code, I am no longer getting the cors error. The only issue is that I want it to only work for google.com and I tested this on several sights and I am not getting a cors error. The reason why I chose google.com is just for testing, I have other domains I need to add once I am in production. I would also like to specify more than one allow origin in my next.config. Is this possible? Thanks to anyone that can help! |
Beta Was this translation helpful? Give feedback.
-
This is something that actually works !! import { NextResponse } from 'next/server'
export const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}
export function middleware(request: Request) {
if (request.method === 'OPTIONS') {
return NextResponse.json({}, { headers: corsHeaders })
}
}
export const config = {
matcher: '/api/:path*',
} Add this under middleware.ts under app dir |
Beta Was this translation helpful? Give feedback.
-
the solutions above are not working for me with POST |
Beta Was this translation helpful? Give feedback.
-
I solved this just by adding and setting up the OPTIONS method. Here is the code:
|
Beta Was this translation helpful? Give feedback.
-
this worked for me in middleware.ts
|
Beta Was this translation helpful? Give feedback.
-
I've run into this issue several different times. According to the documentation you can just set the relevant headers in
But this unfortunately doesn't work. I've got a few different types of solution working
Is there a recommended approach? I'd like to get a recommended solution that I can stick with rather than having to exhaustively test all the endpoints with CORS regularly. Another issue with relevant discussion: #48224 |
Beta Was this translation helpful? Give feedback.
-
Found a working solution for applying CORS via middleware instead of applying per-route. This solution includes preflight check so that import { NextRequest, NextResponse } from "next/server"
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
}
export function middleware(request: NextRequest) {
if (request.method === "OPTIONS") {
return NextResponse.json({}, { headers: corsHeaders })
}
const response = NextResponse.next()
Object.entries(corsHeaders).forEach(([key, value]) => {
response.headers.append(key, value)
})
return response
}
export const config = {
matcher: "/api/:path*",
} This file is named |
Beta Was this translation helpful? Give feedback.
-
I believe this is resolved with #63264 and the workarounds won't be needed once it's merged. |
Beta Was this translation helpful? Give feedback.
-
The documentation (https://nextjs.org/docs/app/building-your-application/routing/middleware) states that middleware functions only work with edge runtime. So... I had to define OPTIONS function for each route, leading to considerable repetition of logic. To address this, I did something like below; // api/some/route.ts
import {resJson} from 'inSomeFiles'
export { OPTIONS } from 'inSomeFiles'
export async function GET() {
return resJson('Hellow Next.js')
}
// inSomeFiles.ts
import { NextResponse } from 'next/server';
export async function OPTIONS() {
return NextResponse.json(null, { headers: corsHeaders });
}
export function resJson<T>(value: T, options?: Parameters<typeof NextResponse.json>[1]) {
return NextResponse.json(value, { headers: corsHeaders, ...options });
}
export const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
} |
Beta Was this translation helpful? Give feedback.
Added an example to the docs: