When you send a request to n8n directly from a frontend inside a browser you get CORS issues unless you are requesting from the same domain.
This is not technically an issue with n8n, but instead this is a security “feature” that browsers have to protect users.
However, since we’re not able to set what we need in n8n to deal with this currently it would be nice to add this as a feature or guide for users that want to blend n8n with traditional coded frontends
The basic solution is to just use a proxy, but this can be impractical / not ideal for a couple of reasons:
You happen to be using a statically generated frontend site from a framework like Nuxt.js / Next.js so you can’t proxy directly using a framework like Axios
You don’t want to pay extra for a server just to proxy requests to avoid CORS
You’re using some no-code frontend builder where it could be complicated to deal with a situation like this
Here’s some background on what we need to fix this issue
the server needs to send the Access-Control-Allow-Origin response header because requests trigger a CORS preflight, and so then the browser does an OPTIONS preflight.
**The solution is to configure the server to send the Access-Control-Allow-Originresponse header** and to handle theOPTIONS` request
Originally I have also had the impression that n8n should have handled CORS but at the end of the day, I guess that is architecturally safer to use a proxy instead.
I am using Lambda Functions on AWS to handle the POSTING of the data and the Authentication.
my requests to AWS API Gateway have 2 arguments {action,payload} with action I am passing the Webhook path (ashcode) and the payload is the data then I am posting. The AWS Lambda Environment Variables can handle the ENDPOINT URL and the base64 encoded combination of user:password used as basic auth for the webhook. AWS API Gateway has all the CORS configuration that you will need to setup in order to send the request to n8n and in the lambda function you can use fetch to proxy the request.
I tried the same setup but with a different workflow vendor - Pipedream. There was no CORS issue there but replacing Pipedream with n8n prevented me to handle responses in the web application on production website (not locally hosted).
If anyone stumbles upon this, I’ve worked around the cors limitations by setting up a super simple docker nginx container that proxies traffic through to n8n with cors enabled:
# default.conf
# replace variables with actual host/port names
# ${NGINX_UPSTREAM_HOST}:${NGINX_UPSTREAM_PORT}
server {
listen 80;
location / {
# add cors headers
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
# Only requests matching the whitelist expectations will
# get sent to the application server
proxy_pass http://${NGINX_UPSTREAM_HOST}:${NGINX_UPSTREAM_PORT};
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
}
}