โœ… What is CORS?

CORS stands for Cross-Origin Resource Sharing. It's a security mechanism implemented by browsers to restrict web pages from making requests to a different domain than the one that served the web page.

For example:

Frontend (React): http://localhost:3000
Backend (API): http://localhost:5000

By default, a frontend served from port 3000 cannot make a request to port 5000 unless the backend explicitly allows it.

โš ๏ธ Why Does the CORS Error Occur?

When a frontend JavaScript application (like React) tries to fetch or POST data to a different domain or port, the browser checks if the backend server has allowed that origin.

If not, you'll see this error:

Access to fetch at 'http://localhost:5000/api/data' from origin 'http://localhost:3000' has been blocked by CORS policy...

๐Ÿ”ฅ Common CORS Issues in React Projects

  1. CORS error while calling API on development
  2. Missing headers on backend (Access-Control-Allow-Origin)
  3. Preflight OPTIONS requests failing
  4. Authentication with cookies across domains
  5. Using third-party APIs with no CORS support

๐Ÿš€ Solution 1: Fixing CORS in Node.js/Express Backend

Install the cors middleware:

npm install cors

In your server.js or app.js:

const express = require('express');
const cors = require('cors');

const app = express();

// Allow specific origin
app.use(cors({
  origin: 'http://localhost:3000',
  credentials: true
}));

app.get('/api/data', (req, res) => {
  res.json({ message: 'Hello from backend!' });
});

app.listen(5000, () => console.log('Server running on port 5000'));

โœ… Handling Preflight Requests

Browsers send a preflight OPTIONS request when the request method is not GET/POST or uses custom headers.

Ensure Express handles it:

app.options('*', cors()); // Preflight

๐Ÿ”’ With Credentials (JWT/Auth)

If you're sending cookies (e.g., JWT token stored in cookies):

Frontend:

fetch('http://localhost:5000/api/protected', {
  method: 'GET',
  credentials: 'include'
});

Backend:

app.use(cors({
  origin: 'http://localhost:3000',
  credentials: true
}));

Also ensure you're using cookie-parser:

npm install cookie-parser

๐Ÿงช Solution 2: Use Proxy in React (Development Only)

In package.json of React:

"proxy": "http://localhost:5000"

Now React will proxy API calls, removing the need for CORS in dev.

// No need to specify full URL
fetch('/api/data');

โœ… Pros: Easy in development โŒ Cons: Not usable in production

๐Ÿง  Solution 3: CORS Fix for 3rd-Party APIs (Proxy Server)

If you're calling an API without CORS support, use a proxy server like:

https://cors-anywhere.herokuapp.com/
fetch('https://cors-anywhere.herokuapp.com/https://example.com/api')

Or use a self-hosted proxy:

npm install express-http-proxy

โš ๏ธ Common Mistakes to Avoid

  • Setting * for Access-Control-Allow-Origin when using credentials (this will fail)
  • Forgetting to include credentials: true in fetch()
  • Not handling OPTIONS requests
  • Misconfigured reverse proxies (Nginx/AWS API Gateway)

๐Ÿง  Bonus: CORS in Production

  • Always whitelist specific domains (never use *).
  • Use helmet or similar packages for HTTP header protection.
  • Configure your reverse proxy (like Nginx) to handle CORS properly.

Example (Nginx):

location /api/ {
    add_header 'Access-Control-Allow-Origin' 'https://yourdomain.com';
    add_header 'Access-Control-Allow-Credentials' 'true';
}

โœจ Final Thoughts

CORS is a security feature, not a bug. Instead of disabling it recklessly, understand how to configure your backend correctly.

TL;DR:

  • Use cors middleware in Node.js
  • Use proxy in React for local development
  • Be cautious with credentials and Access-Control-Allow-Origin
  • Handle preflight OPTIONS properly