To prepare

Be clear about one thing first: cross-domain is a browser limitation

So it’s not that you can’t access it, it’s that the browser is blocking it for its own reasons.

As for what browsers are worried about (what is cross-domain and why is it cross-domain), see: Baidu

The idea behind CORS is to tell the browser, “Don’t worry, I’m ok with this request, let him access it.” The idea behind JSONP is to request the SRC attribute in a way that browsers don’t worry about: the SRC attribute in script tags (other tags with SRC attributes, such as IMG, will do as well).

To simulate a cross-domain scenario, start the simplest Node service locally and return query parameters.

// create a new server.js file that requires node const HTTP = require('http');
const querystring = require('querystring');

const server = http.createServer((req, res) => {
  const query = querystring.parse(req.url.split('? ') [1]); const queryStr = JSON.stringify(query); res.writeHead(200, {"Content-type": "text/plain; charset=utf-8"
  });
  res.end(queryStr);
});

server.listen(9999);
console.log('server run at 9999');
Copy the code

Start the service

node server.js
Copy the code

Go to http://127.0.0.1:9999/ directly in your browser first? Name = useless scholar &age=25 See return no problem

Then open the console in F12 on the current page (you are now reading the article nuggets page) and create an Ajax request in the console

var xhr = new XMLHttpRequest();
xhr.open('get'.'http://127.0.0.1:9999/? Name = age=25');
xhr.send();
Copy the code

A cross – domain error occurs after execution

CORS

First of all, let’s take a look at the cross-domain principle of CORS. In fact, the error in the written very clear, we access the resource does not set the header of the access source of gold.

In THE rules of CORS, requests are divided into simple requests and non-simple requests. The one we sent above is a simple request.

For simple and non-simple requests, see CORS Cross-domain Principles

For simple requests

Just specify which access sources are allowed in the response header.

Add access-Control-allow-Origin to the response header in server.js

const http = require('http');
const querystring = require('querystring');

const server = http.createServer((req, res) => {
  const query = querystring.parse(req.url.split('? ') [1]); const queryStr = JSON.stringify(query); res.writeHead(200, {"Content-type": "text/plain; charset=utf-8"."Access-Control-Allow-Origin": "*"// * allows all source access}); res.end(queryStr); }); server.listen(9999); console.log('server run at 9999');
Copy the code

Restart the Node service and try again

Access-control-allow-origin has taken effect and data has been obtained successfully

For non-simple requests

Change the above request method from GET to PUT, request again (put method is not simple request)

var xhr = new XMLHttpRequest();
xhr.open('put'.'http://127.0.0.1:9999/? Name = age=25');
xhr.send();
Copy the code

You can see that the cross-domain error occurs again

The response header you just set is still there, but it doesn’t work anymore. In addition, you can see here that we originally sent a PUT request, but the request method said options. For non-simple requests, the browser sends a precheck first. If the precheck passes, the browser will send a real request

The resource we accessed was not set to allow access to the PUT method

Add access-Control-allow-methods to the response header in server.js and set the request to Allow the PUT method

const http = require('http');
const querystring = require('querystring');

const server = http.createServer((req, res) => {
  const query = querystring.parse(req.url.split('? ') [1]); const queryStr = JSON.stringify(query); res.writeHead(200, {"Content-type": "text/plain; charset=utf-8"."Access-Control-Allow-Origin": "*"."Access-Control-Allow-Methods": "GET, POST, PUT"}); res.end(queryStr); }); server.listen(9999); console.log('server run at 9999');
Copy the code

When you restart the service and request again, you can see that the cross-domain error message disappears

You can also see that a precheck request is still made first, which passes, and the PUT request continues

Non-simple requests also restrict the information in the request header. Again, the principle is the same: Access-Control-allow-headers is ok to set the allowed Access Headers in the return header, for example

var xhr = new XMLHttpRequest();
xhr.open('put'.'http://127.0.0.1:9999/? Name = age=25');
xhr.setRequestHeader("X-Corx-Test"."aabbcc");
xhr.send();
Copy the code

Set to allow the x-corx-test header

const http = require('http');
const querystring = require('querystring');

const server = http.createServer((req, res) => {
  const query = querystring.parse(req.url.split('? ') [1]); const queryStr = JSON.stringify(query); res.writeHead(200, {"Content-type": "text/plain; charset=utf-8"."Access-Control-Allow-Origin": "*"."Access-Control-Allow-Methods": "GET, POST, PUT"."Access-Control-Allow-Headers": "X-Corx-Test"
  });

  res.end(queryStr);
});

server.listen(9999);
console.log('server run at 9999');
Copy the code

JSONP

Because nuggets did CSP processing, jSONP could not be tested, and baidu was used for demonstration.

What is CSP, reference: Ruan Yifeng’s blog

Delete the configuration of CORS from the Node service

const http = require('http');
const querystring = require('querystring');

const server = http.createServer((req, res) => {
  const query = querystring.parse(req.url.split('? ') [1]); const queryStr = JSON.stringify(query); res.writeHead(200, {"Content-type": "text/plain; charset=utf-8"
  });

  res.end(queryStr);
});

server.listen(9999);
console.log('server run at 9999');
Copy the code

Open the console on baidu home page F12. At this time, if we use Ajax to request our service, we will report a cross-domain error

As mentioned above, the principle of JSONP is to create a JSONP request in the Console using the SRC of the script tag, which is not restricted by the browser across domains

var script = document.createElement('script');
script.src = 'http://127.0.0.1:9999/? Name = age=25';
document.head.appendChild(script);
Copy the code

After execution, there is no error when you see this time

The way to get the data is to define a function on the front end to receive the data, and then execute this function in the js returned by the back end, and pass in the data to be returned as a parameter. For example, define a function called getData on the front end

var script = document.createElement('script');
script.src = 'http://127.0.0.1:9999/? Name = age=25';
document.head.appendChild(script);
function getData(res) {
  console.log(res);
}
Copy the code

Call this function from the content returned at the back end to pass in the data

const http = require('http');
const querystring = require('querystring');

const server = http.createServer((req, res) => {
  const query = querystring.parse(req.url.split('? ') [1]); const queryStr = JSON.stringify(query); res.writeHead(200, {"Content-type": "text/plain; charset=utf-8"});let jsonpStr = `getData(${queryStr}) `; res.end(jsonpStr); }); server.listen(9999); console.log('server run at 9999');
Copy the code

After the service is restarted, the front-end code is executed and the data is retrieved

The name of this function should be consistent with the convention and it is best to remove the script tag after retrieving the data

var script = document.createElement('script');
script.src = 'http://127.0.0.1:9999/? Name = age=25';
document.head.appendChild(script);
function getData(res) {
  console.log(res);
  document.head.removeChild(script);
}
Copy the code