Good intentions! I drew 10 diagrams of the principles of 7 cross domain solutions and made them into diagrams!

preface

Hello, I'm Lin Sanxin. Speaking the most difficult knowledge in the most easy to understand words is my motto. The foundation is advanced, and the premise is my original intention.

It is necessary for us to connect the front-end interface with the back-end interface, but many students may ignore a possible problem in the docking process - cross domain. What is cross domain? Why cross domain? How can we solve it?

Why cross domain?

Why do cross domain problems occur? Then we have to talk about the browser's homology policy. It stipulates that the protocol number, domain name and port number must be the same in order to comply with the homology policy

If one is different, cross domain problems will occur. The consequences of non-compliance with the source policy are

  • 1. Browser memory such as localstore, SessionStorge and cookies cannot be accessed across domains
  • 2. DOM nodes cannot operate across domains
  • 3. Ajax requests cannot cross domain requests

Note: one IP can register multiple different domain names, that is, multiple domain names may point to the same IP. Even so, they do not comply with the source policy

Cross domain timing?

When does cross domain occur? I tested many students and got two answers

  • 1. As soon as the request was sent, it was stopped by the browser's cross domain error report (most people answered)
  • 2. The request is sent to the back-end, which returns data. When the browser receives the back-end data, it is stopped by the browser's cross domain error message

What kind is it? We can verify that we first npm i nodemon -g, then create an index.js, and then nodemon index starts 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 Sanxin'));
}).listen(port, function () {
    console.log('server is listening on port ' + port);
})

Create another index.html to write the request code of the front end. Let's write a simple AJAX request

// index.html  http://127.0.0.1:5500/index.html
<script>
    //Step 1: create an asynchronous object
    var ajax = new XMLHttpRequest();
    //Step 2: set the url parameters of the request. The first parameter is the type of the request, and the second parameter is the url of the request, which can take parameters
    ajax.open('get', 'http://127.0.0.1:8000?name = Lin Sanxin from the front end ');
    //Step 3: send request
    ajax.send();
    //Step 4: the registration event onreadystatechange will be called when the state changes
    ajax.onreadystatechange = function () {
        if (ajax.readyState == 4 && ajax.status == 200) {
            //Step 5: if you can enter this judgment, the data has come back perfectly, and the requested page exists
            console.log(ajax.responseText);//Enter the corresponding content
        }
    }

</script>

In the end, the front end does report errors across domains. But this is not the result. If we want to know which answer is, the key is to see whether there is output from the back-end node service at a glance. So answer 2 is right.

Same domain & & cross domain?

The same origin policy mentioned earlier. If the protocol number - domain name - port number are the same, they are the same domain. Otherwise, they are cross domain, which will lead to cross domain error reporting. Let's consolidate our understanding of the same domain and cross domain through several examples!

Solutions across domains

Cross domain is actually a problem for a long time, and there are many corresponding solutions. Read on!!!

JSONP

As we said earlier, the existence of browser homology strategy leads to cross domain problems. Is there anything that is not bound by cross domain problems? In fact, there are. The following three tag loading resource paths are not bound

  • 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 makes use of the src loading of script, which is not bound, so it can have the ability to get data from different domains. However, JSONP needs the cooperation of front-end and back-end to realize the final cross domain data acquisition.

JSONP, in a popular sense, is to use the src of script to send a request and pass a method name callback to the back end. The back end gets the method name, splices the required data into a new string callback (required data) through the string, and sends it to the front end. After receiving the string, the front end will automatically execute the method callback (required data). As the old rule, first the figure above, and then the code.

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}Years old!!!`
        const str = `${callback}(${JSON.stringify(person)})` // Spell callback(data)
        res.end(str);
    } else {
        res.end(JSON.stringify('Nothing, you'));
    }
}).listen(port, function () {
    console.log('server is listening on port ' + port);
})

Front end code

// index.html  http://127.0.0.1:5500/index.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 Sanxin ', age: 23},' callback '). Then (data = >{
        console.log(data) // Lin Sanxin is 23 years old!!!
    })

The disadvantage of JSONP is that it requires front-end and back-end cooperation, and only supports get request methods

WebSocket

What is WebSocket? In fact, I don't know much about it, but I won't copy MDN data directly like others, because I believe you can't understand it.

I understand that WebSocket is a protocol (at the same level as http), and it can carry out cross domain communication. Why does it support cross domain communication? I found an article here Why can WebSocket cross domain? , very good

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}Years old!!!`)
    })
})

Front end code

// index.html  http://127.0.0.1:5500/index.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 Sanxin ', age: 23}). Then (data = >{
        console.log(data) // Lin Sanxin is 23 years old!!!
    })

give the result as follows

Cors

Cors, the full name of which is cross origin resource sharing, means cross domain resource sharing. Cors is generally enabled by the back end. Once enabled, the front end can access the back end across domains.

Why can the front end request the back end across domains when the back end turns on Cors? My understanding is: the front end accesses the back end across domains, the back end turns on Cors, and sends the access control allow origin: domain name field to the front end (actually more than one) , the front-end browser judges that if the access control allow origin domain name is the same as the front-end domain name, the browser will not implement cross domain interception, so as to solve the cross domain problem.

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) {
    // Turn on Cors
    res.writeHead(200, {
        //Set the domain name that allows cross domain, or * allow all domain names
        'Access-Control-Allow-Origin': 'http://127.0.0.1:5500',
        //Cross domain allowed request methods, or set * to allow all methods
        "Access-Control-Allow-Methods": "DELETE,PUT,POST,GET,OPTIONS",
        //Allowed header types
        'Access-Control-Allow-Headers': 'Content-Type'
    })
    const { query: { name, age } } = urllib.parse(req.url, true);
    res.end(`${name}this year ${age}Years old!!!`);
}).listen(port, function () {
    console.log('server is listening on port ' + port);
})

Front end code

// index.html  http://127.0.0.1:5500/index.html
    //Step 1: create an asynchronous object
    var ajax = new XMLHttpRequest();
    //Step 2: set the url parameters of the request. The first parameter is the type of the request, and the second parameter is the url of the request, which can take parameters
    ajax.open('get', 'http://127.0.0.1:8000?name = Lin Sanxin & age = 23 ');
    //Step 3: send request
    ajax.send();
    //Step 4: the registration event onreadystatechange will be called when the state changes
    ajax.onreadystatechange = function () {
        if (ajax.readyState == 4 && ajax.status == 200) {
            //Step 5: if you can enter this judgment, the data has come back perfectly, and the requested page exists
            console.log(ajax.responseText);//Enter the corresponding content
        }
    }

give the result as follows

Node interface proxy

Let's go back to the same origin policy. The same origin policy is just a policy of the browser. It is not restricted to the back end, that is, the front-end back-end will be restricted by the same origin policy, but the back-end back-end will not be restricted. Therefore, you can access the back-end 1 with Cors set first through the Node interface agent, and then let the back-end 1 access the back-end 2 to obtain data to the back-end 1, and then the back-end 1 transmits the data to the back-end 1 To front end

Backend 2 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) {
    console.log(888)
    const { query: { name, age } } = urllib.parse(req.url, true);
    res.end(`${name}this year ${age}Years old!!!`)
}).listen(port, function () {
    console.log('server is listening on port ' + port);
})

Create an index2.js and nodeon index2.js

Backend 1 code

// index2.js  http://127.0.0.1:8888

const http = require('http');
const urllib = require('url');
const querystring = require('querystring');
const port = 8888;

http.createServer(function (req, res) {
    // Turn on Cors
    res.writeHead(200, {
        //Set the domain name that allows cross domain, or * allow all domain names
        'Access-Control-Allow-Origin': 'http://127.0.0.1:5500',
        //Cross domain allowed request methods, or set * to allow all methods
        "Access-Control-Allow-Methods": "DELETE,PUT,POST,GET,OPTIONS",
        //Allowed header types
        '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: '8000',
        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);
})

Front end code

// index.html  http://127.0.0.1:5500

//Step 1: create an asynchronous object
    var ajax = new XMLHttpRequest();
    //Step 2: set the url parameters of the request. The first parameter is the type of the request and the second parameter is the url of the request. You can dynamically pass the parameter starName to the server with parameters
    ajax.open('get', 'http://127.0.0.1:8888?name = Lin Sanxin & age = 23 ');
    //Step 3: send request
    ajax.send();
    //Step 4: the registration event onreadystatechange will be called when the state changes
    ajax.onreadystatechange = function () {
        if (ajax.readyState == 4 && ajax.status == 200) {
            //Step 5: if you can enter this judgment, the data has come back perfectly, and the requested page exists
            console.log(ajax.responseText);//Enter the corresponding content
        }
    }

give the result as follows

Nginx

In fact, Nginx and Node interface proxy are the same thing, but Nginx doesn't need us to build an intermediate service ourselves

Download first nginx , and then modify nginx.conf under nginx directory as follows:

    server{
        listen 8888;
        server_name  127.0.0.1;
 
        location /{
            proxy_pass 127.0.0.1:8000;
        }
    }

Finally, start nginx from the command line nginx -s reload

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}Years old!!!`);
}).listen(port, function () {
    console.log('server is listening on port ' + port);
})

Front end code

// index.html  http://127.0.0.1:5500

//Step 1: create an asynchronous object
    var ajax = new XMLHttpRequest();
    //Step 2: set the url parameters of the request. The first parameter is the type of the request and the second parameter is the url of the request. You can dynamically pass the parameter starName to the server with parameters
    ajax.open('get', 'http://127.0.0.1:8888?name = Lin Sanxin & age = 23 ');
    //Step 3: send request
    ajax.send();
    //Step 4: the registration event onreadystatechange will be called when the state changes
    ajax.onreadystatechange = function () {
        if (ajax.readyState == 4 && ajax.status == 200) {
            //Step 5: if you can enter this judgment, the data has come back perfectly, and the requested page exists
            console.log(ajax.responseText);//Enter the corresponding content
        }
    }

give the result as follows

postMessage

Scenario: http://127.0.0.1:5500/index.html The iframe tag is used in the page, and a http://127.0.0.1:5555/index.html Page of

Although the two pages exist in one page, they need iframe tags to be nested. Communication between the two pages is not possible because their port numbers are different. According to the homology policy, there is a cross domain problem between them

What should I do? The two pages can communicate using postMessage

// 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 Sanxin', age: 23 }, 'http://127.0.0.1:5555')
        window.onmessage = function (e) {
            console.log(e.data) // Lin Sanxin is 23 years old!!!
        }
    }
</script>
// 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}Years old!!!`, origin)
        }
</script>

document.domain && iframe

Scenario: communication between a.sanxin.com/index.html and b.sanxin.com/index.html

In fact, the above two cannot communicate under normal circumstances, because their domain names are different and belong to cross domain communication

Then what shall I do? In fact, they have one thing in common, that is, their secondary domain name is sanxin.com, which enables them to communicate through document.domain & & iframe

Since this rookie has no server for the time being, it is temporarily simulated using local

// 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>
// 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>

give the result as follows

epilogue

Keywords: Javascript node.js Front-end ECMAScript chrome

Added by cuvaibhav on Mon, 29 Nov 2021 09:49:12 +0200