Cross-Origin and Same-Origin Strategies: JSONP, CORS, Proxy, Nginx, WebSocket, postMessage, and document.domain
This article explains the concepts of cross‑origin and same‑origin policies, and demonstrates multiple solutions—including JSONP, CORS headers, proxy servers, Nginx configuration, WebSocket communication, postMessage, and document.domain—providing both front‑end and back‑end code examples for each method.
Introduction: Cross-Origin and Same-Origin Policy
Cross‑origin occurs when a web page requests resources from a different origin (different protocol, domain, or port). The same‑origin policy protects user data by restricting direct communication between origins, with a few exceptions such as img, link, and script tags.
JSONP Implementation
JSONP bypasses the same‑origin restriction by using a script tag whose src attribute is not subject to the policy. The client supplies a callback parameter, the server wraps the data in a call to that function, and the browser executes the global callback.
function jsonp(url, cb) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
// Register a global callback
window[cb] = function(data) {
resolve(data);
};
// Set the script src with the callback query
script.src = `${url}?cb=${cb}`;
// Append to trigger the request
document.body.appendChild(script);
});
}
// Use the jsonp function
jsonp('http://localhost:3000', 'callback').then(res => {
console.log(res); // output result
});Backend for JSONP
const http = require('http');
http.createServer(function(req, res) {
const query = new URL(req.url, `http://${req.headers.host}`).searchParams;
if (query.get('cb')) {
const cb = query.get('cb'); // e.g., 'callback'
const data = 'hello world';
const result = `${cb}("${data}")`;
res.end(result);
}
}).listen(3000);CORS Implementation
CORS allows the server to specify permitted origins via the Access-Control-Allow-Origin response header, enabling the browser to relax the same‑origin check for the request.
// Front‑end request using XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:3000');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
}; // Backend that sets CORS header
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, {
'Access-Control-Allow-Origin': 'http://127.0.0.1:5500'
});
res.end('Hello World');
}).listen(3000);Proxy Server
A proxy forwards the request from the front‑end to the target server, acting as an intermediate layer that can add the appropriate CORS headers or simply hide the cross‑origin request from the browser.
// Front‑end request to proxy server
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://192.168.1.63:3000');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
}; // Backend proxy implementation (Node.js)
const http = require('http');
http.createServer(function(req, res) {
// Allow any origin
res.writeHead(200, { "access-control-allow-origin": "*" });
// Forward request to target server
const options = {
host: '192.168.1.63',
port: '3000',
path: '/',
method: 'GET',
headers: {}
};
http.request(options, proxyRes => {
proxyRes.on('data', data => {
res.end(data.toString());
});
}).end();
}).listen(3000);Nginx Proxy
Using Nginx as a reverse proxy provides the same effect as a Node proxy, forwarding requests and optionally setting CORS headers. (Diagram omitted for brevity.)
WebSocket Implementation
WebSocket connections are not subject to the same‑origin policy in the same way as HTTP; they can be used for cross‑origin communication after the initial handshake.
// Front‑end helper using WebSocket
function myWebSocket(url, params = {}) {
return new Promise((resolve, reject) => {
const socket = new WebSocket(url);
socket.onopen = () => {
socket.send(JSON.stringify(params));
};
socket.onmessage = e => {
resolve(e.data);
};
});
}
myWebSocket('ws://localhost:3000', {age: 18}).then(res => {
console.log(res);
}); // Backend WebSocket server (Node.js with ws library)
const WebSocket = require('ws');
const ws = new WebSocket.Server({ port: 3000 });
ws.on('connection', client => {
client.on('message', data => {
client.send('Welcome');
setInterval(() => {
client.send('Ping');
}, 2000);
});
});postMessage Communication
The postMessage API enables safe cross‑origin messaging between windows, iframes, or workers by specifying the target origin.
<!-- index.html (parent page) -->
<body>
<h2>Home</h2>
<iframe id="frame" src="http://127.0.0.1:5500/postMessage/detail.html" width="800" height="500"></iframe>
<script>
const obj = {name: 'midsummer', age: 18};
document.getElementById('frame').onload = function() {
this.contentWindow.postMessage(obj, 'http://127.0.0.1:8080');
window.onmessage = e => console.log(e.data);
};
</script>
</body> <!-- detail.html (iframe) -->
<body>
<h3>Detail – <span id="title"></span></h3>
<script>
const title = document.getElementById('title');
window.onmessage = e => {
const {data: {name, age}, origin} = e;
title.innerText = `${name} ${age}`;
e.source.postMessage(`midsummer now ${++age} years`, origin);
};
</script>
</body>document.domain Technique
When two pages share the same top‑level domain, setting document.domain to that shared domain relaxes the same‑origin restriction, allowing direct access between the pages.
<!-- index.html -->
<body>
<h2>Home</h2>
<iframe id="frame" src="http://127.0.0.1:5500/postMessage/detail.html" width="800" height="500"></iframe>
<script>
document.domain = '127.0.0.1';
document.getElementById('frame').onload = function() {
console.log(this.contentWindow.data);
};
</script>
</body> <!-- detail.html -->
<script>
document.domain = '127.0.0.1';
var data = 'domain';
</script>By setting the same document.domain value on both pages, the same‑origin restriction is effectively lifted, enabling seamless communication.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
