Running into CORS issue in my nextjs project

Hello,

My app is working fine in my local and in vercel prod.

However in preview env, i am running into CORS issue since my api url is different from preview url.
My preview URL changes each time I merge my code with deploy branch so I cannot whitelist specific URL

Error in my browser console
"Access to XMLHttpRequest at 'https://www.tennisduo.com/api/...' from origin 'https://tennisduo-7vjgavgu4-sgudipati2s-projects.vercel.app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."

I have done below 3 changes but my issue still exists

  1. next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  async headers() {
    return [
      {
        // matching all API routes
        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
  1. vercel.json
{
  "headers": [
    {
      "source": "/api/(.*)",
      "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"
        }
      ]
    }
  ]
}
  1. middleware.js
import { NextResponse } from 'next/server'

export function middleware(request) {
  // Handle simple requests
  const response = NextResponse.next()

  // Add the CORS headers to the response
  response.headers.set('Access-Control-Allow-Origin', '*')
  response.headers.set(
    'Access-Control-Allow-Methods',
    'GET, POST, PUT, PATCH, DELETE, OPTIONS'
  )
  response.headers.set(
    'Access-Control-Allow-Headers',
    'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
  )

  return response
}

export const config = {
  matcher: '/api/:path*'
}

Hey, @sgudipati2! Great to have you join us in the Vercel Community :smile:

The CORS issue in your preview environment stems from the mismatch between your API URL and the preview URL. The solution lies in configuring CORS on your API server (tennisduo.com) rather than in your preview deployment.

You could try removing all CORS configurations from your preview deployment files. Instead, modify the next.config.js on your API server to allow requests from Vercel preview URLs by setting the Access-Control-Allow-Origin header to https://*.vercel.app . Make sure your API server correctly handles OPTIONS preflight requests.

Another thing you can try is using environment variables for your API URL to avoid cross-origin requests in preview deployments. Set NEXT_PUBLIC_API_URL appropriately for each environment (local, preview, production).

From a security standpoint, remember to use more specific patterns for allowed origins rather than wildcards when possible.

Let us know how you get on!

I wanted to loop back in to share our latest community post that may be helpful with CORS issues: