LogoTRUONG PHAM
Home
Projects
Blogs
YouTube
Contact

Newsletter

Stay updated with technical artifacts and engineering insights.

LogoTRUONG PHAM

Building scalable software and sharing insights on technology & life.

Sitemap

  • Home
  • Projects
  • Blogs
  • YouTube
  • Contact

Connect

  • GitHub
  • LinkedIn
  • Email
  • YouTube

© 2024 TRUONG PHAM. © All rights reserved.

Privacy PolicyTerms of Service
Back
Blog #43: CORS Isn't Always the Backend's Fault
50 FRONTEND LESSONS – HARD-EARNED EXPERIENCES

Blog #43: CORS Isn't Always the Backend's Fault

When the bright red error named CORS appears and the habit of Frontend developers blaming the Backend.

TP
Truong PhamSoftware Engineer
PublishedAugust 15, 2024

To me in my early days of working,

"Hey, Backend hasn't enabled CORS yet!". You shouted that in the Slack group chat when you saw a bright red error covering the console. You assumed that seeing a CORS error meant the Backend guys forgot to configure Access-Control-Allow-Origin.

That day, you spent the entire afternoon arguing with the Backend team, while in reality, the problem lay right in your own local proxy configuration file.

Simple Problem: What is CORS?

In layman's terms, CORS (Cross-Origin Resource Sharing) is a browser security lock. It prevents website A (your localhost) from calling data from website B (the API server) without consent. It's a mechanism to protect users, but for us developers, it's often a nightmare.

Current Perspective: When the "Victim" is the "Perpetrator"

Now I understand that CORS errors appear not only when the server isn't configured, but also when:

  1. You send the wrong Header (e.g., missing Authorization or wrong Content-Type).
  2. You encounter a 500 error or a Redirect at the Server (the browser doesn't receive the CORS header when a response fails).
  3. You forget to configure the Proxy in your development environment.

A common junior mistake is that whenever they see CORS, they ask the Backend to put an asterisk * (allowing all sources). This is a very serious security vulnerability in a production environment.

// Junior mistake: Indiscriminate configuration or blaming
// Instead of finding out why the request was blocked
axios.get('https://api.example.com/data', {
  headers: { 'X-Custom-Header': 'foobar' } // This header can trigger a Preflight request and cause a CORS error if not declared
});

Why Does It Cause Problems?

In production, misconfiguring CORS can lead to your application being completely paralyzed when a user accesses from a different domain, or simply features like "Image Upload" being blocked because the browser doesn't allow sending files to another origin without proper configuration for the OPTIONS method.

Comparison of Solutions:

  • Quick fix: Ask the Backend to open CORS wide with an asterisk *. Dangerous and unprofessional.
  • Sustainable way:
    • Locally: Use a Proxy (like setupProxy.js in React or Vite/Webpack config) to fool the browser into thinking the request is being sent from the same origin.
    • In Production: Work with the Backend to specify an exact Whitelist of allowed domains. Understand Preflight Requests (OPTIONS method) to configure headers correctly.

Practical Lesson

Next time you see a CORS error, don't rush to blame. Open the Network tab, look at the OPTIONS method request, see what the Access-Control-Request-Headers header is requesting and what the server is returning.

Be an engineer who understands HTTP protocols deeply, rather than just someone who knows how to call an API.


Notes on understanding cross-domain boundaries.

Series • Part 43 of 50

50 FRONTEND LESSONS – HARD-EARNED EXPERIENCES

NextBlog #44: CI/CD and Environment Variables that 'Disappear' Without a Trace
Blog #42: When the Backend Changes the Schema and the Fragility of the Frontend
38Blog #38: Micro-frontend Reality Check – When theoretical glory meets harsh reality39Blog #39: The 'Will Fix Later' Promise and the Compound Interest of Technical Debt40Blog #40: Don't try to be smart – Write code for humans, not for machines41Blog #41: The 2 AM Panic and Infinite Question Marks42Blog #42: When the Backend Changes the Schema and the Fragility of the Frontend43Blog #43: CORS Isn't Always the Backend's FaultReading44Blog #44: CI/CD and Environment Variables that 'Disappear' Without a Trace45Blog #45: The Brutal Difference Between Staging and Production46Blog #46: Feature Flag – The 'Lifebuoy' for Risky Releases47Blog #47: Long-term Tab Crash – What happens when Users never close their Tabs?48Blog #48: Slow AI UX Fail – When User Experience can't wait for Artificial Intelligence
TP

Written by Truong Pham

Software Engineer passionate about building high-performance systems and meaningful experiences.

Read more articles