What is cross-domain
Simply put, this is a document or script from one source accessing a document or script from another source (also known as an interaction). This is an interaction between two sources that do not meet the same origin policy
Same-origin policy?
This is a mechanism of the browser. The Same Origin policy is a convention, which is the most core and basic security function of the browser. If the Same Origin policy is missing, the normal functions of the browser may be affected. The Web is built on the same origin policy, and browsers are just an implementation of the same origin policy.
Why the same Origin policy
The same origin policy is a behavior of the browser to protect local data from being contaminated by data retrieved by JavaScript code. Therefore, the same origin policy intercepts data received from the client. That is, the request is sent and the server responds, but the browser cannot receive the request
What is the same origin policy
Let’s look at the part of the url www.zjx.com:80/path/myfile…
- http://: this part is the protocol part of the browser
- www.zjx.com: This section is the domain name section
- :80: This part is the port part
- /path/myfile: This part is the request pathName part
- ? Key = ValuE1&Name = ZJX: This part is the request parameters (search) part
All of the above can be obtained with localtion. XXX, for example, to obtain the request parameter: localtion.search. Will return? key=value1&name=zjx
The same origin policy means that the protocal, port, and domain name must be the same to be considered as the same origin. If there is only one difference, it is not the same origin and cross-domain is generated. Ports are generally not written (can be omitted).
Let’s see which of the following are homologous and which are not (www.zjx.com:80/path/myfile…
-
http://www.zjx.com/path/kkk.html: homologous
-
http://www.kkk.com/path/kkk.html: different source (domain name)
-
http://v2.www.kkk.com/path/kkk.html: different source (domain name)
-
http://www.kkk.com:81/path/kkk.html: different source (port)
-
https://www.kkk.com/path/kkk.html: different source (agreement)
Now let’s look at how do we solve cross-domain
1.JSONP
How does JSONP cross domains?
SONP implements cross-domain requests simply by creating them on the fly<script>
Tag, and then use<script>
SRC is not constrained by the same origin policy to obtain data across domains
Let’s take a look at making a native request using Ajax:
<script text="text/javascript"> window.onload = function() { var Btn = document.getElementById('btn'); Btn.onclick = function() {var XHR = new XMLHttpRequest(); // With the XMLHttpRequest object, You can define the function xhr.onReadyStatechange = function() {if (xhr.status == 200) {alert(' request successful ')}} // two methods to relax the request to the server, Open and send //open receives three parameters, open(method, URL,true) //method: request method. Url: request address. Xhr.open ('get', 'http://localhost:4000', true) xhr.send()}} </script>Copy the code
When we click send request: no doubt cross-domain, then we will use JSONP to achieve cross-domain data
Using the jSONP front end:
<button id=" BTN "> </button> <! <script> function show(data) {console.log(data); } var BTN = document.getelementById (' BTN ') btn.adDeventListener ('click',function(){// create a script tag let script = document.createElement('script') script.src='http://localhost:4000? callback=show' document.body.appendChild(script) }) </script>Copy the code
Node version: The backend uses HHTP to create a service
const http = require('http'); const querystring = require('querystring') var data = { status: 200, message: 'I have heard of love, } const server = http.createserver () server.on('request', function (req, const server = http.createserver () server.on('request', function (req, Const KKK = req.url.split('? ')[1] const jjj = kkk.split('=')[1] const callback = jjj res.end(`${callback}(${JSON.stringify(data)}); `); }) server.listen(4000, function () {console.log('4000 port started '); })Copy the code
Final result:
Koa version
const Koa = require('koa'); const app = new Koa(); var data = { status: 200, message: } // Response app.use(CTX => {const KKK = ctx.url.split('? ')[1] const jjj = kkk.split('=')[1] const callback = jjj ctx.body = `${callback}(${JSON.stringify(data)}); `}); App.listen (4000,function(){console.log('4000 started '); });Copy the code
Results:
Express version
const express = require('express') const app = express() var data = { status: 200, message: 'I have heard of love, } app.get('/', function (req, res) { var callback=req.query.callback res.send(`${callback}(${JSON.stringify(data)}); `) }) app.listen(4000)Copy the code
Results:
Let’s encapsulate a JSONP
<script> function jsonp({ url, params, Callback}) {let dataStr = "// For (let key in params) {dataStr += ${key}=${params[key]}& '} dataStr += 'callback=${callback} document.createElement('script') script.src = `${url}? ${dataStr}` console.log(script.src); Document. The body. The appendChild (script) / / implement the callback function (scheme 1) / / Windows/callback = (data) = > {. / / the console log (data); } // return new Promise((resolve, reject) => { window[callback] = data => { resolve(data) document.body.removeChild(script) } }) } jsonp({ url: 'http://localhost:4000', params: { name: 'zjx', age: 18 }, callback: 'show' }).then(data=>{ console.log(data); }) </script>Copy the code
Results:
Summary: JSONP only supports GET requests (too limited)
2. Cors (usually done at the back end)
A quick introduction to CORS: CORS requires both browser and server support. Currently, all browsers support this function, and Internet Explorer cannot be lower than Internet Explorer 10.
The entire CORS communication process is completed automatically by the browser without user participation. For developers, CORS communication is no different from same-origin AJAX communication, and the code is exactly the same. As soon as the browser discovers that an AJAX request crosses the source, it automatically adds some additional headers, and sometimes an additional request, but the user doesn’t feel it.
Therefore, the key to CORS communication is the server. As long as the server implements the CORS interface, cross-source communication is possible.
There are simple requests and non-simple requests
So first we have to know what a simple request is, and once we know a simple request what’s left is a non-simple request, right
As long as the following two conditions are met, it is a simple request
(1) Request method is one of the following three methods:
- get
- post
- head
(2) HTTP headers do not exceed the following fields:
- Accept Sets the type of content accepted (request headers)
- Accept-language Sets the accepted Language (request header)
- Content-language Sets the natural Language or target user Language for the closed Content (response header)
- Last-Event-ID
- Content-type: Sets the MIME Type of the request body (for POST and PUT requests) to three values
application/x-www-form-urlencoded
,multipart/form-data
,text/plain
Any request that does not meet both conditions is a non-simple request.
Browsers treat these two requests differently.
Let’s take a look firstA simple requestHow do I use CORS
The backend: const http = require('http') const data={ status:200, Message :' use cors across domain '} const server= http.createserver (function(req,res){// res.writehead (200,{// // "Content-type ":"text/plain", // Set the Type of the request header //" access-Control-allow-origin ":"*", // // "access-Control-allow-headers ":"", //}) res.end(json.stringify (data))}) server.listen(4000,()=>{console.log('4000 service started '); })Copy the code
We make a request from the front end and back end:
<Button id=' BTN '> </Button> <script> var BTN = document.getelementById (' BTN ') btn.adDeventListener ('click',()=>{// Var XHR =new XMLHttpRequest() xhr.onReadyStatechange =function (res){if(xhr.status== 200&&xhr.readyState ==4){if(xhr.status== 200&&xhr.readyState ==4){ Alert (' request successful ') console.log(xhr.responsetext); } } xhr.open('get','http://localhost:4000') xhr.send() }) </script>Copy the code
Before using any means to cross the domain: the data must not be requested: (port and domain name are different)
Let’s take a look at what information the browser carries when we send the request. (As you can see from the following figure, the browser recognizes that the cross-source AJAX request is a simple request and automatically adds one to the headerOrigin
Field)
In the header above, the Origin field specifies the source (protocol + domain + port) from which the request came. Based on this value, the server decides whether to approve the request or not. So this is where we turn on the server header: look at the code
const http = require('http') const data={ status:200, } const server= http.createserver (function(req,res){res.writehead (200,{// "Content-type ":"text/plain", // Set the Type of the request header to" access-Control-allow-origin ":"*", "Access-control-allow-headers ":"", }) res.end(json.stringify (data))}) server.listen(4000,()=>{console.log('4000 service started '); })Copy the code
This time we go to request can request success!! However, our Origin uses *, which means that anyone can access my server, which is not safe. You can set which sources are allowed to access my server
Request successful! Let’s start with an overview of what field operations can be set across domains:
- Specifies that other domain names are allowed
‘Access – Control – Allow – Origin: http://172.20.0.206’
- General usage (, specify domain, dynamic setting), 3 becauseAuthentication headers and cookies not allowed // Whether to allow subsequent requests to carry authentication information (cookies), the value must be true, otherwise no return
‘Access-Control-Allow-Credentials:true’
- Precheck results cache time, also known as the above mentioned cache
‘Access-Control-Max-Age: 1800’
- The type of request allowed
‘Access-Control-Allow-Methods:GET,POST,PUT,POST’
- Allowed request header fields
‘Access-Control-Allow-Headers:x-requested-with,content-type’
Take a look atNon-simple request
Change the code above: change the get request method to PUT
<Button id=' BTN '> </Button> <script> var BTN = document.getelementById (' BTN ') btn.adDeventListener ('click',()=>{// Var XHR =new XMLHttpRequest() xhr.onReadyStatechange =function (res){if(xhr.status== 200&&xhr.readyState ==4){if(xhr.status== 200&&xhr.readyState ==4){ Alert (' request successful ') console.log(xhr.responsetext); } } xhr.open('put','http://localhost:4000') xhr.send() }) </script>Copy the code
Let’s hit Send request and see what the browser returns, okay?
Since we do not set the type of request allowed on the back end, it will cross domains. Now what does the browser do when it sends this request?
Huh? Sent two requests ???? Yes, it is.
Above, the first request is a precheck request
Preview the request
Non-simple requests are requests that have special requirements on the server, such as the request method being PUT or DELETE, or the content-Type field being of Type Application/JSON.
CORS requests that are not simple requests add an HTTP query, called preflight, before formal communication. The browser first asks the server whether the domain name of the current web page is on the server’s license list, and which HTTP verb and header fields can be used. The browser issues a formal XMLHttpRequest request only if it receives a positive response; otherwise, an error is reported.
If the server approves the precheck request
I’m going to check it outOrigin
,Access-Control-Request-Method
andAccess-Control-Request-Headers
Field, verify that cross-source requests are allowed, and then respond. That is, when we configure the back end with the above three:
const http = require('http') const data={ status:200, } const server= http.createserver (function(req,res){res.writehead (200,{// "Content-type ":"text/plain", // Set the Type of the request header to" access-Control-allow-origin ":'*', "Access-control-allow-headers ":"ontent-type"," access-control-allow-methods ":"PUT", }) res.end(json.stringify (data))}) server.listen(4000,()=>{console.log('4000 service started '); })Copy the code
At this point our request is successful:
Precheck failed: If the server denies the “precheck” request, it will return a normal HTTP response without any CORS related header fields. At this point, the browser decides that the server did not approve the precheck request, and therefore fires an error that is caught by the ONError callback function of the XMLHttpRequest object. The console will print the following error message.
XMLHttpRequest cannot load http://api.alice.com.
Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
Copy the code
Cors is used for the same purpose as JSONP, but is more powerful than JSONP.
JSONP supports only GET requests, and CORS supports all types of HTTP requests. JSONP has the advantage of supporting older browsers and being able to request data from sites that do not support CORS.
Recommend an article here: http://www.ruanyifeng.com/blog/2016/04/cors.html
3.postmessage
First, we need to understand the usage of postmessage:
otherWindow.postMessage(message, targetOrigin, [transfer]); OtherWindow: A reference to another window, such as the contentWindow property of iframe, the window object returned by executing window.open, or the window.frames named or numeric index. Message: Data to be sent to another window. TargetOrigin: Specifies which Windows can receive message events. The value can be * (for unrestricted) or a URI. Transfer: Optional, a string of Transferable objects that are passed at the same time as Message. Ownership of these objects is transferred to the receiver of the message, and ownership is no longer retained by the senderCopy the code
For example: We first have an A page
What does page A do?
Suppose page A wants to receive data from page B. In page A, we open a new page and add a message listening event to the page. Let’s see what page A does
Function test() {let op = window.open('b.html', '_blank'); function receiveMessage(event) { console.log('event', event.data); } op.addEventListener("message", receiveMessage, false); } </script>Copy the code
So, page B needs to send the data from page A to see what page B does. (Page B needs to use PostMessage to send the data to page B.)
// function post() {// window.postmessage ("hi there!"); , location.origin); // } // function receiveMessage(event) { // console.log('event', event.data) // } // window.addEventListener("message", receiveMessage, false); Window.onload = function post() {window.postmessage (" I am the data you requested ", location.origin); } </script>Copy the code
Data sent by a page using PostMessage is sent to all the same pages (unless specified) including the page itself
4.nginx
I have never used an nginx proxy: the request is sent by someone else
When site A requests the 1.js file from site B, it sends A request to site B. Nginx receives the request according to the configuration file and requests the resource from Site B on behalf of Site A. After receiving the resource, Nginx returns it to Site A, thus solving the cross-domain problem.
This directly with other author: https://juejin.cn/post/6947940375008903176#heading-13
5.webscoket
Full duplex bidirectional communication (i.e. both the server and client can send messages)
What are the characteristics?
(1) Based on THE TCP protocol, the implementation of the server side is relatively easy.
(2) It has good compatibility with HTTP protocol. The default ports are also 80 and 443, and the handshake phase uses HTTP protocol, so it is not easy to mask the handshake and can pass various HTTP proxy servers.
(3) The data format is relatively light, the performance overhead is small, and the communication is efficient.
(4) Can send text, can also send binary data.
(5) There is no source restriction, and the client can communicate with any server.
(6) The protocol identifier is WS (if encrypted, WSS), and the server URL is the URL.
Let’s see how we can use webscoket, okay
Create a webscoket service, specify port 8181, and log the received messages.
var WebSocketServer = require('ws').Server, wss = new WebSocketServer({ port: 8181 }); wss.on('connection', function (ws) { console.log('client connected'); ws.on('message', function (message) { console.log(message); Ws. send(' Hello ')}); });Copy the code
Take a look at our client:
Var ws = new WebSocket('ws://localhost:8181'); ws.onopen = function () { console.log('ws onopen'); ws.send('from client: hello'); }; ws.onmessage = function (e) { console.log('ws onmessage'); console.log('from server: ' + e.data); }; </script>Copy the code
Client API
WebSocket constructor
The WebSocket object is used as a constructor to create a new WebSocket instance.
var ws = new WebSocket('ws://localhost:8181');
Copy the code
After executing the above statement, the client will connect to the server.
webSocket.readyState
The readyState property returns the current state of the instance object, of which there are four types.
- CONNECTING: The value is 0, indicating that a connection is being established. - OPEN: the value is 1, indicating that the connection is successful and communication can be started. - CLOSING: The value is 2, indicating that the connection is CLOSING. - CLOSED: the value is 3, indicating that the connection is CLOSED or fails to be opened.Copy the code
webSocket.onopen
The onopen property of the instance object, which specifies the callback function if the connection is successful.
ws.onopen = function () {
console.log('ws onopen');
ws.send('from client: hello');
};
Copy the code
webSocket.onclose
The onClose property of the instance object, which specifies the callback function if the connection is closed.
// ws.onclose = function (evt) {
// console.log("Connection closed.");
// };
Copy the code
webSocket.onmessage
The onMessage property of the instance object, which specifies the callback function to receive data from the server.
ws.onmessage = function (e) {
console.log('ws onmessage');
console.log('from server: ' + e.data);
};
Copy the code
webSocket.send()
The send() method of the instance object is used to send data to the server.
ws.send('your message');
Copy the code
This article in detail: http://www.ruanyifeng.com/blog/2017/05/websocket.html