-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
166: Understanding Same-Origin Policy and CORS
I can almost guarantee that at some point in your career, you're going to run into a console error that looks something like this: Access to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000' has been blocked by CORS policy. It's one of the most frustrating moments for a frontend developer because your code looks perfect, the server is running, and yet the browser is just refusing to let the data through.
Let's look at a piece of code that triggers this. Imagine you're building a weather dashboard and you're trying to pull data from a separate API server.
async function getWeather() {
try {
const response = await fetch('https://weather-api.internal.com/v1/forecast');
const data = await response.json();
console.log(data);
} catch (err) {
console.error('Fetch failed:', err);
}
}
getWeather();
If you run this from your local dev environment, it will fail. You'll see that "CORS policy" error in the DevTools console, and your catch block will trigger. The weird part? If you paste that same URL directly into your browser's address bar, it works perfectly. You'll see the JSON right there on the screen. This discrepancy is where most people get confused.
The Wall: Same-Origin Policy
The reason this happens is the Same-Origin Policy (SOP). This is a fundamental security feature built into every modern browser. Its job is to prevent a malicious website from making requests to another site where you might be logged in (like your bank) and stealing your data using your active session cookies.
A "Origin" is defined by three things: Protocol (http vs https), Domain (localhost vs example.com), and Port (3000 vs 80). If any of these three differ between the site hosting the JS and the server you're calling, the browser considers it a "Cross-Origin" request. By default, the browser lets you send the request, but it blocks the JS from reading the response unless the server explicitly says it's okay.
The Key: Access-Control-Allow-Origin
To fix this, we use CORS (Cross-Origin Resource Sharing). CORS isn't a "JavaScript fix"—it's a server-side configuration. You cannot bypass CORS by writing clever JavaScript on the frontend; that would defeat the whole purpose of the security policy.
The server needs to respond with a specific HTTP header that tells the browser, "I trust this origin, go ahead and let them see the data." The most common header is Access-Control-Allow-Origin.
If you have control over the server (for example, a Node/Express backend), you would fix it like this:
const express = require('express');
const app = express();
// This allows ANY site to access your API. Great for public APIs,
// but dangerous for private data.
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
next();
});
app.get('/v1/forecast', (req, res) => {
res.json({ temp: 72, condition: 'Sunny' });
});
app.listen(3000);
By adding res.setHeader('Access-Control-Allow-Origin', '*'), the server tells the browser that any origin (the * wildcard) is allowed. If you wanted to be more secure, you'd replace the * with your actual domain, like http://localhost:3000.
The "Pre-flight" Request
You might notice something strange in your Network tab: a request with the method OPTIONS that happens right before your actual GET or POST. This is called a Pre-flight request.
The browser does this when the request is "complex"—for example, if you're sending JSON data or using a custom header like Authorization. The browser essentially asks the server: "Hey, I'm about to send a POST request with a JSON body; are you cool with that?" If the server doesn't respond correctly to the OPTIONS request, the browser will never even attempt the real request.
I've seen developers spend hours debugging their POST logic only to realize the server wasn't configured to handle OPTIONS requests. Always check the Network tab first to see if the pre-flight is the part that's failing.
📋 Practical Task
Fixing the Cross-Origin Header in a Mock Server
You are given a mock Node.js server script that is currently blocking requests from your frontend. Your task is to modify the server middleware to allow requests specifically from http://localhost:5173 (a common Vite port) while rejecting everything else.
// server.js
const express = require('express');
const app = express();
// TASK: Modify this middleware to allow only http://localhost:5173
app.use((req, res, next) => {
// Currently, there is no CORS header here, causing the browser to block requests.
// Add the necessary header here.
next();
});
app.get('/api/user', (req, res) => {
res.json({ username: 'DevMentor', status: 'Online' });
});
app.listen(3000, () => console.log('Server running on port 3000'));
Requirements:
- Do not use the
*wildcard; restrict access to the specific origin mentioned. - Ensure the header is set before
next()is called. - Verify that you are using the correct header name:
Access-Control-Allow-Origin.
There are no comments for now.