How to Solve CORS Errors: Practical Frontend and Backend Strategies

This article explains why browsers block cross‑origin requests due to the Same‑Origin Policy, then walks through six practical solutions—including CORS headers, JSONP, Nginx reverse proxy, API gateways, WebSocket, and postMessage—providing code examples for both frontend and Spring Boot backend configurations.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
How to Solve CORS Errors: Practical Frontend and Backend Strategies

Many developers encounter CORS errors when the browser blocks a request that works fine with tools like Postman. The root cause is the browser's Same‑Origin Policy, which treats requests from different protocols, domains, or ports as potentially unsafe.

The policy considers any request that differs in protocol, domain, or port as cross‑origin and blocks it unless the server explicitly allows it.

fetch('http://api.xxx.com:8000/user')
  .then(res => res.json())
  .then(data => console.log(data)); // CORS error in browser

To resolve this, you need a cross‑origin solution that relaxes the browser's restrictions.

2 Solutions to CORS

2.1 CORS (Cross‑Origin Resource Sharing)

Applicable scenarios : front‑back separation projects, APIs used by multiple clients.

CORS is a W3C standard; the backend adds response headers to tell the browser which origins are allowed.

Backend code example (Spring Boot) :

@CrossOrigin(origins = "http://localhost:8080")
@GetMapping("/user")
public User getUser() { /* ... */ }

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8080")
                .allowedMethods("*")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(3600);
    }
}

Key response headers :

Access-Control-Allow-Origin: http://localhost:8080

Access-Control-Allow-Methods: GET,POST

Access-Control-Allow-Credentials: true

Common pitfalls :

If allowCredentials(true) is used, allowedOrigins cannot be "*".

Complex requests (e.g., Content‑Type: application/json) trigger a pre‑flight OPTIONS request that must be handled.

2.2 JSONP

Applicable scenarios : legacy projects, GET‑only third‑party APIs (e.g., map services).

JSONP exploits the fact that <script> tags are not subject to CORS.

Frontend code :

function handleUserData(data) {
    console.log("Received data:", data);
}
const script = document.createElement('script');
script.src = 'http://api.xxx.com:8000/user?callback=handleUserData';
document.body.appendChild(script);

Backend code (Spring Boot) :

@GetMapping("/user")
public String jsonp(@RequestParam String callback) {
    User user = new User("Tony", 30);
    return callback + "(" + new Gson().toJson(user) + ")";
}

Drawbacks :

Only GET requests; limited query length.

Susceptible to XSS attacks.

2.3 Nginx Reverse Proxy

Applicable scenarios : production deployment, micro‑service gateway.

Let Nginx add CORS headers so the browser sees the request as same‑origin.

Nginx configuration example :

server {
    listen 80;
    server_name localhost;
    location /api {
        proxy_pass http://api.xxx.com:8000;
        add_header 'Access-Control-Allow-Origin' 'http://localhost:8080';
        add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type';
    }
}

Frontend then requests /api/user, which Nginx forwards to the real backend.

2.4 API Gateway (e.g., Spring Cloud Gateway, Kong)

Similar to Nginx but integrated into the micro‑service layer.

Spring Cloud Gateway configuration :

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origins: "http://localhost:8080"
            allowed-methods: "*"
            allowed-headers: "*"
            allow-credentials: true

2.5 WebSocket

Applicable scenarios : real‑time communication such as chat or live market data.

WebSocket handshake is not restricted by CORS.

Frontend code :

const socket = new WebSocket('ws://api.xxx.com:8000/ws');
socket.onmessage = event => {
    console.log('Received message:', event.data);
};

Backend code (Spring Boot) :

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new MyWebSocketHandler(), "/ws");
    }
}

2.6 postMessage

Applicable scenarios : communication between a page and an iframe or popup.

Use window.postMessage to exchange data across origins.

// Parent page
const childWindow = window.open('http://child.com');
childWindow.postMessage('I am your parent', 'http://child.com');

// Child page
window.addEventListener('message', event => {
    if (event.origin !== 'http://parent.com') return; // verify source
    console.log('Received from parent:', event.data);
});

Summary

Development : use CORS annotations for quick fixes.

Production : prefer Nginx or API gateway to centralize CORS handling.

Legacy projects : JSONP works but should be avoided for new code.

Real‑time scenarios : adopt WebSocket.

Security : avoid wildcard * in Access-Control-Allow-Origin; use explicit whitelist.

The root cause of CORS issues is the browser’s same‑origin policy, not the HTTP protocol itself.

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.

Spring BootCORSCross-OriginNGINXJSONPpostMessage
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

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.