Mastering CORS: Fix Cross‑Origin Errors with Nginx Proxy

This guide walks through diagnosing common CORS failures, explains the four essential response headers, and provides step‑by‑step Nginx configurations—including handling preflight OPTIONS requests, custom headers, and method restrictions—to reliably resolve cross‑origin issues during development.

Open Source Linux
Open Source Linux
Open Source Linux
Mastering CORS: Fix Cross‑Origin Errors with Nginx Proxy

When a frontend site ( http://localhost:8080) accesses a backend service ( http://localhost:59200) you may encounter CORS errors; first ensure the backend does not already handle CORS and verify the API works with Postman.

CORS relies on four response headers: Access-Control-Allow-Origin – specifies allowed request origins. Access-Control-Allow-Headers – lists permitted custom request headers (validated during preflight). Access-Control-Allow-Methods – enumerates allowed HTTP methods. Access-Control-Allow-Credentials – indicates whether cookies may be sent.

Many tutorials suggest simply adding these headers in Nginx, but real‑world cases often still produce errors because the configuration is incomplete or overridden.

A preflight request (an OPTIONS call) is sent first; the browser expects a successful response with the appropriate headers before issuing the actual request.

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.

Fixing the first error involves adding the missing Access-Control-Allow-Origin header in the Nginx location block:

server {
    listen 22222;
    server_name localhost;
    location / {
        add_header Access-Control-Allow-Origin 'http://localhost:8080';
        proxy_pass http://localhost:59200;
    }
}

If the error persists, ensure the add_header directive is applied with the always flag, because without it the header is only sent for successful (2xx/3xx) responses.

server {
    listen 22222;
    server_name localhost;
    location / {
        add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
        proxy_pass http://localhost:59200;
    }
}

When the preflight request itself returns a non‑200 status (e.g., 404), add a rule to return 204 for OPTIONS requests:

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;
    }
}

If the browser reports that a custom header such as authorization is not allowed, include it in Access-Control-Allow-Headers within the preflight block:

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;
        }
        proxy_pass http://localhost:59200;
    }
}

For HTTP methods other than GET/POST (e.g., PUT), add them to Access-Control-Allow-Methods during the preflight response:

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;
        }
        proxy_pass http://localhost:59200;
    }
}

Using a wildcard ( *) for Access-Control-Allow-Headers and Access-Control-Allow-Methods is possible, but Access-Control-Allow-Origin should remain specific for security.

If the backend already handles CORS, remove the Nginx headers to avoid duplicate Access-Control-Allow-Origin values, which browsers reject.

Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*', 'http://localhost:8080', but only one is allowed.

Finally, a complete Nginx configuration that covers all discussed cases might look like this:

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;
    }
}

Choosing either server‑side CORS handling or Nginx proxy handling—never both—keeps the setup clear and maintainable.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Web DevelopmentCORSCross-Originhttp-headerspreflight
Open Source Linux
Written by

Open Source Linux

Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.