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 CookieThe browser memory cannot be accessed across domains
  • 2,DOM nodeUnable to operate across domains
  • 3,An Ajax requestUnable 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