Mastering CORS: Step-by-Step Nginx Proxy Solutions for Common Errors
This guide walks through diagnosing and fixing typical CORS problems by configuring Nginx as a proxy, explaining the four essential response headers, handling preflight requests, and providing complete server blocks for various error scenarios.
When you encounter CORS issues, don't immediately copy random solutions; read this comprehensive guide first.
Preparation:
Frontend address: http://localhost:8080
Backend address: http://localhost:59200
Ensure the backend does not handle CORS and verify the API works with Postman.
CORS mainly involves four response headers:
Access-Control-Allow-Origin – specifies allowed request origins.
Access-Control-Allow-Headers – lists permitted custom request headers (checked during preflight).
Access-Control-Allow-Methods – enumerates allowed HTTP methods (checked during preflight).
Access-Control-Allow-Credentials – indicates whether cookies can be sent; set to true only when necessary.
Many articles suggest simply adding these headers in Nginx, but configurations can still fail.
Preflight requests are OPTIONS requests sent by browsers to verify allowed origins, methods, and headers before the actual request.
Example Nginx proxy configuration (port 22222):
<code>server {
listen 22222;
server_name localhost;
location / {
proxy_pass http://localhost:59200;
}
}</code>Testing the proxy shows the API is reachable.
When the frontend (8080) accesses the proxied API, several error cases appear.
Case 1
<code>Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.</code>The error indicates the preflight response lacks
Access-Control-Allow-Origin. Add the header in Nginx:
<code>server {
listen 22222;
server_name localhost;
location / {
add_header Access-Control-Allow-Origin 'http://localhost:8080';
proxy_pass http://localhost:59200;
}
}</code>After adding, the same error persists because the header is not always returned.
Case 2
<code>Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.</code>The OPTIONS request receives no 2xx status. Return a 204 for OPTIONS:
<code>server {
listen 22222;
server_name localhost;
location / {
add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://localhost:59200;
}
}</code>Case 3
<code>Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.</code>Add the missing header to the preflight response:
<code>server {
listen 22222;
server_name localhost;
location / {
add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Headers 'authorization';
return 204;
}
proxy_pass http://localhost:59200;
}
}</code>After fixing, the error reverts to Case 1, showing that multiple
add_headerdirectives can interfere. Nginx inherits headers only when none are defined at the current level.
There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.
To avoid inheritance issues, separate handling for OPTIONS and non‑OPTIONS requests:
<code>server {
listen 22222;
server_name localhost;
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin 'http://localhost:8080';
add_header Access-Control-Allow-Headers 'authorization';
return 204;
}
if ($request_method != 'OPTIONS') {
add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
}
proxy_pass http://localhost:59200;
}
}</code>Case 4
When using a method other than GET/POST (e.g., PUT), the preflight response must include it in
Access-Control-Allow-Methods:
<code>Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.</code>Add the method:
<code>server {
listen 22222;
server_name localhost;
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin 'http://localhost:8080';
add_header Access-Control-Allow-Headers 'content-type,authorization';
add_header Access-Control-Allow-Methods 'PUT';
return 204;
}
if ($request_method != 'OPTIONS') {
add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
}
proxy_pass http://localhost:59200;
}
}</code>Setting
Access-Control-Allow-Headersand
Access-Control-Allow-Methodsto
*works, but
Access-Control-Allow-Originshould be specific for security.
Case 5
If the backend already handles CORS, duplicate
Access-Control-Allow-Originheaders can appear, causing the error:
<code>Access-Control-Allow-Origin header contains multiple values '*', http://localhost:8080, but only one is allowed.</code>In such situations, choose either backend CORS handling or Nginx proxy handling, not both.
Complete Nginx configuration example (replace
*with your needs):
<code>server {
listen 22222;
server_name localhost;
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin 'http://localhost:8080';
add_header Access-Control-Allow-Headers '*';
add_header Access-Control-Allow-Methods '*';
add_header Access-Control-Allow-Credentials 'true';
return 204;
}
if ($request_method != 'OPTIONS') {
add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
add_header Access-Control-Allow-Credentials 'true';
}
proxy_pass http://localhost:59200;
}
}</code>Following these steps should resolve most CORS problems encountered during development.
Efficient Ops
This public account is maintained by Xiaotianguo and friends, regularly publishing widely-read original technical articles. We focus on operations transformation and accompany you throughout your operations career, growing together happily.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.