CORS Issue with Netlify Function and Widget Integration

Setup

I’m building a feedback widget that can be embedded on any website. The architecture is:

  • Main app hosted on Netlify (userbird.netlify.app)
  • Widget script (widget.js) loaded from my domain into client websites
  • Netlify Function handling feedback submissions

Current Configuration

netlify.toml

[[headers]]
  for = "/*"
  [headers.values]
    Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' https://userbird.netlify.app; style-src 'self' 'unsafe-inline'; connect-src 'self' https://userbird.netlify.app/.netlify/functions/* https://*.supabase.co *; frame-ancestors 'none'; form-action 'self'; upgrade-insecure-requests;"
    X-Content-Type-Options = "nosniff"
    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"
    Referrer-Policy = "strict-origin-when-cross-origin"

Netlify Function (feedback/index.ts)

function getCorsHeaders(origin: string | undefined) {
  return {
    'Access-Control-Allow-Origin': origin || '*',
    'Access-Control-Allow-Headers': 'Content-Type, Accept, Origin',
    'Access-Control-Allow-Methods': 'POST, OPTIONS',
    'Access-Control-Max-Age': '86400',
    'Content-Type': 'application/json'
  }
}

The Issue

When the widget tries to submit feedback from a client website (example.com), here’s what I see in the Network tab:

  1. An OPTIONS preflight request to https://userbird.netlify.app/.netlify/functions/feedback/
  • Status: Failed
  • Request Headers:
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type,accept,origin
Origin: http://example.com
  1. The POST request never gets made because the preflight fails

Could someone help me understand what I might be missing in my CORS configuration? I’ve already tried:

  • Added CORS headers to both OPTIONS and POST responses in the Netlify Function
  • Configured CSP in netlify.toml to allow connections
  • Set up specific headers for the widget.js file
  • Validated that the function URL is correct

But the preflight request is still failing.

Code repository

Any guidance would be greatly appreciated, thanks in advance!

Hey @dmenchaca Thanks for raising a question in the forums! Looking at your code, it seems you need to update your functions code to return the CORS headers. The docs detail this limitation here where the header rules don’t apply to dynamic calls such as serverless functions so you really only need them there.

I saw your comment about already trying this, however I think your codebase might be in a bad state causing confusion for you.

Looking at the codebase there are two function files attempting to do the same thing: netlify/functions/feedback.ts and netlify/functions/feedback/index.ts The latter file has cors headers set but the former does not. That said, I would not expect to see both of these files. Usually, developers would use one or the other approach for placing the function in your repo not both. My guess is that you’re attempting to fix the issue in the netlify/functions/feedback/index.ts but, based on Netlify’s precedence ordering, the netlify/functions/feedback.ts is the function that’s being invoked.

Looking at the two functions, they’re doing the same job. My suggestion would be to delete the netlify/functions/feedback.ts file and now your other function file should be the one that gets invoked and includes the CORS headers as expected.

Let us know if that helps!

@SeanRoberts thanks a ton for your detailed response :pray:

I went ahead and deleted netlify/functions/feedback.ts and CORS error persists.

Link to my updated repo.

Here’s my current setup:

  1. My function already includes CORS headers:
function getCorsHeaders(origin: string | undefined) {
  return {
    'Access-Control-Allow-Origin': origin || '*',
    'Access-Control-Allow-Headers': 'Content-Type, Accept, Origin',
    'Access-Control-Allow-Methods': 'POST, OPTIONS',
    'Access-Control-Max-Age': '86400',
    'Content-Type': 'application/json'
  }
}
  1. I’m applying these headers in all responses from the function
  2. The function handles OPTIONS requests correctly
  3. I’ve removed CORS headers for functions from netlify.toml as per your advice

An example scenarios where I’m seeing the CORS errors:

Could there be something else I’m missing?

Thanks! :heart_hands:

This has nothing to do with CORS, but instead because your site simply doesn’t have the Function. This is your deploy: Deploy details | Deploys | userbird | Netlify, which says:

Going to the Function logs page also says no functions: Functions | Logs | userbird | Netlify

Even in your screenshot, the URL returns a 404. You’re not deploying the Function at all. Your deploys appear to be manual deploys and I assume you might be dragging-n-dropping the output. That method works only for static pages and does not deploy Functions. You need to use Git-based deploys or CLI to deploy Functions.

@hrishikesh thanks for the reply.

I see your point.

I’m currently building this web app using Bolt.new and their “Deploy” to Netlify button.

I’m guessing there is no way then for me to deploy functions using Bolt.new’s “Deploy” button? Not even if I define that function and the deploy instructions in my code?

That’s a question for Bolt than Netlify, I’m afraid. They most likely use Netlify API to deploy and while it’s possible to use the API to deploy Functions, I don’t know if Bolt does it or not. When deploying via API, Netlify won’t run any build, it will deploy whatever you send as it is. So your deploy instructions do not make a difference.

@hrishikesh issue solved.

I deployed using Netlify’s github integration and the function was created.

Thanks again to you and @SeanRoberts for the help.

Feel free to mark this thread as closed.