This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.
preface
Hello, I’m Lin Sanxin. It is my motto to tell the most difficult knowledge points in the most easy to understand words. The basis is to advance the premise is my original intention.
We do front-end, usually with the back-end docking interface that is a necessary thing, but many students may ignore a docking process may occur in the problem — cross-domain, that cross-domain is what? Why does it cross domains? How can it be solved?
Why cross domains?
Why do cross-domain problems occur? The browser’s same origin policy specifies that the protocol number, domain name, and port number must be the same
If there is a difference, there will be cross-domain problems, do not conform to the same origin policy results in
- 1.
LocalStorge, SessionStorge, and Cookie
The browser memory cannot be accessed across domains - 2,
DOM node
Unable to operate across domains - 3,
An Ajax request
Unable to request across domains
Note: An IP address can register multiple domain names, meaning that multiple domain names may refer to the same IP address, and even then, they do not comply with the same-origin policy
Cross-domain timing?
When does cross-domain happen? I tested many students and got two answers
- 1. The request was blocked by a cross-domain error from the browser as soon as it was sent (most people answered)
- 2. The request is sent to the backend, which returns the data and is blocked by the browser’s cross-domain error when receiving the backend data
So which one is it? NPM I nodemon-g create an index.js and nodemon index create a node service
/ / index. Js http://127.0.0.1:8000
const http = require('http');
const port = 8000;
http.createServer(function (req, res) {
const { query } = urllib.parse(req.url, true);
console.log(query.name)
console.log('Back end')
res.end(JSON.stringify('Lin Three Hearts'));
}).listen(port, function () {
console.log('server is listening on port ' + port);
})
Copy the code
Create an index.html for the front-end request code, so let’s write a simple AJAX request
http://127.0.0.1:5500/index.html / / index. The HTML
<script>
// Step 1: Create an asynchronous object
var ajax = new XMLHttpRequest();
// Step 2: Set the request URL parameters. Parameter 1 is the request type, parameter 2 is the request URL, can take parameters
ajax.open('get'.'http://127.0.0.1:8000? Name = Lin Sanxin from the front end);
// Step 3: Send the request
ajax.send();
// Step 4: Register the event onreadyStatechange to be called when the status changes
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
// Step 5 If the judgment can be reached, the data returned perfectly, and the requested page exists
console.log(ajax.responseText);// Enter the corresponding content
}
}
</script>
Copy the code
In the end, the front end did report a cross-domain error. But this is not the result, and the key to finding out which answer is which is to see if there is output from the node service at the back end. So, answer 2 is correct.
Codomain case && cross domain case?
Before mentioned the same origin policy, meet the protocol number – domain name – port number these three are the same is the same-domain, otherwise is cross-domain, will lead to cross-domain error, the following through a few examples to let you consolidate the understanding of the same-domain and cross-domain!
Solutions across domains
In fact, cross-domain is a long time problem, there are many corresponding solutions, read on together!!
JSONP
As we said, is there anything that isn’t bound by cross-domain problems because of the same origin policy in browsers? In fact, there is, the following three tag load resource path is unfettered
- 1. Script tag:
<script SRC =" load resource path "></script>
- 2. Link tag:
<link herf=" load resource path "></link>
- 3. Img tag:
<img SRC =" load resource path "></img>
JSONP takes advantage of script’s unfettered SRC loading, giving it the ability to fetch data from different fields. However, JSONP requires front-end and back-end cooperation to achieve the ultimate cross-domain data acquisition.
JSONP stands for: Script SRC to send a request, pass a method name callback to the back end, the back end takes the method name, splices the required data into a new string callback(required data), and sends it to the front end. The method callback(required data) is automatically executed. Same old rule — diagram first, code second.
The back-end code
/ / index. Js http://127.0.0.1:8000
const http = require('http');
const urllib = require('url');
const port = 8000;
http.createServer(function (req, res) {
const { query } = urllib.parse(req.url, true);
if (query && query.callback) {
const { name, age, callback } = query
const person = `${name}This year,${age}Age!! `
const str = `${callback}(The ${JSON.stringify(person)}) ` / / Mosaic callback (data)
res.end(str);
} else {
res.end(JSON.stringify('Nothing, you.'));
}
}).listen(port, function () {
console.log('server is listening on port ' + port);
})
Copy the code
The front-end code
http://127.0.0.1:5500/index.html / / index. The HTML
const jsonp = (url, params, cbName) = > {
return new Promise((resolve, reject) = > {
const script = document.createElement('script')
window[cbName] = (data) = > {
resolve(data)
document.body.removeChild(script) } params = { ... params,callback: cbName }
const arr = Object.keys(params).map(key= > `${key}=${params[key]}`)
script.src = `${url}?${arr.join('&')}`
document.body.appendChild(script)
})
}
jsonp('http://127.0.0.1:8000', { name: 'Lin Three Hearts'.age: 23 }, 'callback').then(data= > {
console.log(data) // Lin Sanxin is 23 years old!!
})
Copy the code
The downside of JSONP is that it requires front-and-back coordination and only supports get request methods
WebSocket
What is a WebSocket? In fact, I do not understand, but I will not copy the MDN data directly like others, because I believe that you can not understand the copy.
WebSocket is a protocol (the same as HTTP, it is a protocol) and it can carry out cross-domain communication, why does it support cross-domain communication? I found an article here why WebSocket can cross domains? That’s a good point
The back-end code
Install NPM I WS first
/ / index. Js http://127.0.0.1:8000
const Websocket = require('ws');
const port = 8000;
const ws = new Websocket.Server({ port })
ws.on('connection'.(obj) = > {
obj.on('message'.(data) = > {
data = JSON.parse(data.toString())
const { name, age } = data
obj.send(`${name}This year,${age}Age!! `)})})Copy the code
The front-end code
http://127.0.0.1:5500/index.html / / index. The HTML
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: / / 127.0.0.1:8000', { name: 'Lin Three Hearts'.age: 23 }).then(data= > {
console.log(data) // Lin Sanxin is 23 years old!!
})
Copy the code
The results are as follows
Cors
Cors, full name is cross-origin Resource Sharing, which means cross-domain Resource Sharing. Cors is generally started by the back end. Once started, the front end can access the back end across domains.
Why can the front end request the back end across domains if the back end turns on Cors? The front end accesses the back end across domains, the back end enables Cors, and sends access-Control-allow-Origin: The domain name field is sent to the front end (in fact, there is more than one domain name). The front end browser determines that the domain name of Access-Control-Allow-Origin is the same as the domain name of the front end. Therefore, the browser does not implement cross-domain interception to solve the cross-domain problem.
The back-end code
/ / index. Js http://127.0.0.1:8000
const http = require('http');
const urllib = require('url');
const port = 8000;
http.createServer(function (req, res) {
/ / open Cors
res.writeHead(200, {
* Allow all domain names
'Access-Control-Allow-Origin': 'http://127.0.0.1:5500'.// Allow request methods across domains, or * allow all methods
"Access-Control-Allow-Methods": "DELETE,PUT,POST,GET,OPTIONS".// The allowed header type
'Access-Control-Allow-Headers': 'Content-Type'
})
const { query: { name, age } } = urllib.parse(req.url, true);
res.end(`${name}This year,${age}Age!! `);
}).listen(port, function () {
console.log('server is listening on port ' + port);
})
Copy the code
The front-end code
http://127.0.0.1:5500/index.html / / index. The HTML
// Step 1: Create an asynchronous object
var ajax = new XMLHttpRequest();
// Step 2: Set the request URL parameters. Parameter 1 is the request type, parameter 2 is the request URL, can take parameters
ajax.open('get'.'http://127.0.0.1:8000? Name = age=23');
// Step 3: Send the request
ajax.send();
// Step 4: Register the event onreadyStatechange to be called when the status changes
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
// Step 5 If the judgment can be reached, the data returned perfectly, and the requested page exists
console.log(ajax.responseText);// Enter the corresponding content}}Copy the code
The results are as follows
Node interface proxy
Or return to the same origin policy, the same-origin policy it is just a strategy of the browser, it is not limit the backend, namely after the front – end will be the same-origin policy limitations, but after the end – after the end, will not be restricted, so you can through the Node interface agent, access has been set up Cors backend 1 first, then let the back-end 1 to access back-end 2 to get the data to the back-end 1, Back-end 1 then passes the data to the front-end
Back-end 2 code
/ / index. Js http://127.0.0.1:8000
const http = require('http');
const urllib = require('url');
const port = 8888;
http.createServer(function (req, res) {
console.log(888)
const { query: { name, age } } = urllib.parse(req.url, true);
res.end(`${name}This year,${age}Age!! `)
}).listen(port, function () {
console.log('server is listening on port ' + port);
})
Copy the code
Create an index2.js and nodmeon index2.js
Back-end 1 code
/ / index2. Js http://127.0.0.1:8888
const http = require('http');
const urllib = require('url');
const querystring = require('querystring');
const port = 8000;
http.createServer(function (req, res) {
/ / open Cors
res.writeHead(200, {
* Allow all domain names
'Access-Control-Allow-Origin': 'http://127.0.0.1:5500'.// Allow request methods across domains, or * allow all methods
"Access-Control-Allow-Methods": "DELETE,PUT,POST,GET,OPTIONS".// The allowed header type
'Access-Control-Allow-Headers': 'Content-Type'
})
const { query } = urllib.parse(req.url, true);
const { methods = 'GET', headers } = req
const proxyReq = http.request({
host: '127.0.0.1'.port: '8888'.path: ` /?${querystring.stringify(query)}`,
methods,
headers
}, proxyRes= > {
proxyRes.on('data'.chunk= > {
console.log(chunk.toString())
res.end(chunk.toString())
})
}).end()
}).listen(port, function () {
console.log('server is listening on port ' + port);
})
Copy the code
The front-end code
http://127.0.0.1:5500 / / index. The HTML
// Step 1: Create an asynchronous object
var ajax = new XMLHttpRequest();
// Step 2: Set the url parameters of the request. Parameter 1 is the type of the request, and parameter 2 is the URL of the request. You can dynamically pass parameter starName to the server
ajax.open('get'.'http://127.0.0.1:8888? Name = age=23');
// Step 3: Send the request
ajax.send();
// Step 4: Register the event onreadyStatechange to be called when the status changes
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
// Step 5 If the judgment can be reached, the data returned perfectly, and the requested page exists
console.log(ajax.responseText);// Enter the corresponding content}}Copy the code
The results are as follows
Nginx
In fact, Nginx is the same as Node proxy, but Nginx does not require us to build an intermediate service
Download nginx first, and then to nginx directory nginx. Conf modified as follows:
server{ listen 8888; Server_name 127.0.0.1; The location / {proxy_pass 127.0.0.1:8000; }}Copy the code
Finally, start nginx on nginx -s reload
The back-end code
/ / index. Js http://127.0.0.1:8000
const http = require('http');
const urllib = require('url');
const port = 8000;
http.createServer(function (req, res) {
const { query: { name, age } } = urllib.parse(req.url, true);
res.end(`${name}This year,${age}Age!! `);
}).listen(port, function () {
console.log('server is listening on port ' + port);
})
Copy the code
The front-end code
http://127.0.0.1:5500 / / index. The HTML
// Step 1: Create an asynchronous object
var ajax = new XMLHttpRequest();
// Step 2: Set the url parameters of the request. Parameter 1 is the type of the request, and parameter 2 is the URL of the request. You can dynamically pass parameter starName to the server
ajax.open('get'.'http://127.0.0.1:8888? Name = age=23');
// Step 3: Send the request
ajax.send();
// Step 4: Register the event onreadyStatechange to be called when the status changes
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
// Step 5 If the judgment can be reached, the data returned perfectly, and the requested page exists
console.log(ajax.responseText);// Enter the corresponding content}}Copy the code
The results are as follows
postMessage
Scene: http://127.0.0.1:5500/index.html pages were used in the embedded in the iframe tag a page of http://127.0.0.1:5555/index.html
Although the two pages exist in the same page, they need iframe tags to be nested. The two pages cannot communicate with each other because they have different port numbers. According to the same origin policy, there is a cross-domain problem between them
So what should we do? Using postMessage, the two pages can communicate
HTTP: / / 127.0.0.1:5500 / index. HTML
<body>
<iframe src="http://127.0.0.1:5555/index.html" id="frame"></iframe>
</body>
<script>
document.getElementById('frame').onload = function () {
this.contentWindow.postMessage({ name: 'Lin Three Hearts'.age: 23 }, 'http://127.0.0.1:5555')
window.onmessage = function (e) {
console.log(e.data) // Lin Sanxin is 23 years old!!}}</script>
Copy the code
/ / http://127.0.0.1:5555/index.html
<script>
window.onmessage = function (e) {
const { data: { name, age }, origin } = e
e.source.postMessage(`${name}This year,${age}Age!! `, origin)
}
</script>
Copy the code
document.domain && iframe
Scenario: Communication between a.sanxin.com/index.html and b.sanxin.com/index.html
In fact, the above two normally cannot communicate, because their domain names are different, belonging to cross-domain communication
So what to do? In fact, they have one thing in common, that is, their secondary domain name is sanxin.com, which allows them to communicate through document.domain && iframe
Because this rookie does not have a server temporarily, so temporarily use local to simulate
/ / http://127.0.0.1:5500/index.html
<body>
<iframe src="http://127.0.0.1:5555/index.html" id="frame"></iframe>
</body>
<script>
document.domain = '127.0.0.1'
document.getElementById('frame').onload = function () {
console.log(this.contentWindow.data) // Lin Sanxin is 23 years old!!
}
</script>
Copy the code
/ / http://127.0.0.1:5555/index.html
<script>
// window.name=" Lin Sanxin is 23 years old!!"
document.domain = '127.0.0.1'
var data = 'Lin Sanxin is 23 years old!! ';
</script>
Copy the code
The results are as follows
conclusion
If you think this article is a little bit helpful to you, click a like and encourage Lin Sanxin haha. Or you can join my shoal of fish. If you want to enter the learning group and shoal of fish, please click here to shoal of fish. I will broadcast the mock interview regularly and answer your questions