Frontend Development 14 min read

Resolving CORS Issues with Nginx Proxy: A Step‑by‑Step Guide

This article walks through the root causes of CORS errors, explains the four essential response headers, demonstrates how to test with Postman, and provides a series of Nginx configuration examples that progressively fix preflight, header, method, and credential problems for a local development environment.

Architecture Digest
Architecture Digest
Architecture Digest
Resolving CORS Issues with Nginx Proxy: A Step‑by‑Step Guide

When you encounter a cross‑origin (CORS) problem, do not immediately copy random solutions; first read the whole article to understand the underlying principles. The guide shows how to reproduce the issue, test the backend with Postman, and then solve it by configuring Nginx as a reverse proxy.

Preparation

Frontend address: http://localhost:8080 Backend address: http://localhost:59200

Ensure the backend does not handle CORS and that the API works correctly with Postman.

CORS mainly involves four response headers

Access-Control-Allow-Origin – specifies allowed request origins (checked for both preflight and actual requests).

Access-Control-Allow-Headers – lists special request headers allowed (checked only during preflight).

Access-Control-Allow-Methods – lists HTTP methods allowed (checked only during preflight).

Access-Control-Allow-Credentials – indicates whether cookies can be sent with cross‑origin requests (checked for both preflight and actual requests).

What is a preflight request?

When a cross‑origin request is made, the browser first sends an OPTIONS request to ask the server whether the origin, methods, and headers are permitted. Only after a positive response does the browser send the real request.

Simulation

Configure Nginx to listen on port 22222 and proxy to the backend:

server {
    listen       22222;
    server_name  localhost;
    location / {
        proxy_pass http://localhost:59200;
    }
}

Testing the proxy shows the backend is reachable.

Case 1 – Missing Access-Control-Allow-Origin

The browser reports: Response to preflight request doesn’t pass access control check: No 'Access-Control-Allow-Origin' header is present . Adding the header in the Nginx location block fixes the error, but the header must be added with the always flag to ensure it appears on both preflight and actual responses.

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

Case 2 – Preflight request does not return HTTP 200/204

The error indicates the OPTIONS request did not receive a successful status. Adding a rule to return 204 for OPTIONS resolves it:

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

Case 3 – Missing authorization in Access-Control-Allow-Headers

The preflight response lacks the authorization header, causing the browser to block the request. Adding the missing header inside the OPTIONS block fixes it:

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

Case 4 – HTTP method not allowed

When the client uses PUT , the preflight response must include it in Access-Control-Allow-Methods . Adding the method resolves the error:

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

Case 5 – Backend already handles CORS

If the backend adds its own CORS headers, Nginx must not duplicate them, otherwise the browser sees multiple Access-Control-Allow-Origin values and blocks the request. Choose either backend handling or Nginx handling, not both.

Final complete configuration (one possible version)

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

After applying the appropriate configuration, the CORS errors disappear and the frontend can successfully call the backend through the Nginx proxy.

ProxyWeb DevelopmentCORSCross-OriginNginxPreflight
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login 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.