Talk about XMLHttpRequest's Ajax and Cross-domain Issues


This article starts with using an XMLHttpRequest object to initiate a GET request, and discusses the same-origin policy and cross-domain and cross-domain implementation.

One, XMLHttpRequest object

MDN:XMLHttpRequest

XMLHttpRequest(XHR) objects are used to interact with the server. Through XMLHttpRequest, you can request a specific URL and get data without refreshing the page. This allows the web page to update the partial content of the page without affecting user operations. XMLHttpRequestIt is widely used in AJAX programming.

Use XMLHttpRequestto send HTTP requests to achieve data exchange between the website and the server.

Send an HTTP request, you need to create an XHRobject, open a URL, and finally send the request. When all these transactions are completed, the object will contain some useful information such as the response body or HTTP status .

Backend preparation

I used express here to simply build a service.

app.js

const express = require('express');
const app = express();
app.all('*', function (req, res, next) {
    
    
  res.header('Access-Control-Allow-Origin', '*'); // 跨域配置
  next();
});
app.get('/api/test', (req, res) => {
    
    
  res.send('hello express');
});
app.listen(3000, () => {
    
    
  console.log('server running at port 3000');
});

Implement a simple ajax request

const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:3000/api/test', true);
xhr.onreadystatechange = function () {
    
    
  if (xhr.readyState === 4) {
    
    
    if (xhr.status === 200) {
    
    
      alert(xhr.responseText);
    }
  }
}
xhr.send(null);

1.open()

The XMLHttpRequest.open() method initiates a request

/**
 * @param method HTTP方法
 * @param url 路径
 * @param async 是否异步
 */
xhr.open(method, url, async);

2.xhr.readyState

The XMLHttpRequest.readyState property returns the current state of an XMLHttpRequest proxy. An XHR agent is always in one of the following states:

value status description
0 UNSENT The proxy was created, but the open() method has not yet been called.
1 OPENED The open() method has been called.
2 HEADERS_RECEIVED The send() method has been called, and the header and status are available.
3 LOADING Downloading; the responseText property already contains some data.
4 DONE The download operation is complete.

How do we view the changes in readyState? This requiresXMLHttpRequest.onreadystatechange

3.xhr.onreadystatechange()

As long as the readyState property changes, the corresponding processing function will be called. This callback function will be called by the user thread. XMLHttpRequest.onreadystatechange will be called when the readystatechange event is triggered when the readyState property of XMLHttpRequest changes.

When readyStatethe value is changed when the callbackfunction is called.

We need to define the callback function mentioned open()before the function. Because of the open call and request initialization, readyState will change from the initial 0 to 1, and we cannot print out the complete process.

const xhr = new XMLHttpRequest();
console.log('UNSENT:', xhr.readyState); // 打印初始readyState
xhr.onreadystatechange = function () {
    
    
  console.log('onreadystatechange:', xhr.readyState);
};
xhr.open('GET', 'http://127.0.0.1:3000/api/test', true);
xhr.send(null);

View in browser

Insert picture description here

4.xhr.status

Read-only property XMLHttpRequest.statusreturns the response status code numbers. Error with XMLHttpRequest before the request is completed, statusthe value is 0. The status code is the standard HTTP status codes .

The code to view the complete status is as follows

const xhr = new XMLHttpRequest();
console.log(`UNSENT:readyState=${
      
      xhr.readyState};status=${
      
      xhr.status}`);
xhr.onreadystatechange = function () {
    
    
  console.log(`onreadystatechange=${
      
      xhr.readyState};status=${
      
      xhr.status}`);
};
xhr.open('GET', 'http://127.0.0.1:3000/api/test', true);
xhr.send(null);

View in browser

Insert picture description here

5.send()

XMLHttpRequest.send()Method is used to send HTTP request. If it is an asynchronous request (the default is an asynchronous request), this method will return immediately after the request is sent; if it is a synchronous request, this method will not return until the response arrives. The XMLHttpRequest.send() method accepts an optional parameter as the request body; if the request method is GET or HEAD, the request body should be set to null.

XMLHttpRequest.send(body)

NOTE: In open()and send()between, we can XMLHttpRequest.setRequestHeader()set up a top request parameters.

Through the above steps, we can send an ajax request.

2. Same-origin strategy and cross-domain

1. What is cross-domain?

Cross-domain means that the browser cannot execute scripts of other websites. It is caused by the browser's same-origin policy and is a security restriction imposed by the browser on JavaScript.

2. Same Origin Strategy

The same-origin policy is a convention. It is the core and most basic security function of the browser. If the same-origin policy is missing, it will cause many security problems.

Same origin refers to the same "protocol + domain name + port".

The same-origin policy restricts the following behaviors:

  • Storage content such as Cookie, LocalStorage and IndexDB
  • DOM and JS objects cannot be obtained
  • Ajax request cannot be sent

Note: It must be noted that cross-domain is a limitation of browsers. When we use a packet capture tool to capture interface data, we can see the interface and return the data. It is only the limitation of the browser, and we cannot obtain the data. Data can be requested using the postman request interface, which once again proves that cross-domain is a browser limitation

Three, several ways to achieve cross-domain

1. JSONP realizes cross-domain

JSONP (JSON with Padding ) json填充?

JSONP is a way to obtain data to solve cross-domain problems

JSONP principle

Principle: Loading static resource files from different domains through corresponding tags in html pages is allowed by the browser

Loading images, css, js can ignore the same-origin policy.

Usage: img can be used for statistics management and third-party statistics services can be used; CDN can be used for link and script. Script can be used to achieve JSONP cross-domain

<img src="跨域的图片地址" />
<link href="跨域的css地址" />
<script src="跨域的js地址"></script>

Key points:

  • Using the <script>label does not restrict cross-domain vulnerabilities, web pages can get JSON data dynamically generated from other sources.
  • JSONP requests must be supported by the server.
  • The limitation is that it can only get requests.

JSONP implementation

We need to know that the server can dynamically splice data back at will. If you return to the page, it needs to conform to the html format, essentially returning some text, then! We can obtain data across domains through script.

First modify the app.js on the server side without setting Access-Control-Allow-Origin

At this point we refresh the browser, you will see the following

Insert picture description here

Now modify the html and backend to implement JSONP cross-domain

index.html

<script>
  window.callback = (data) => {
     
     
    console.log(data);
  }
</script>
<script src="http://127.0.0.1:3000/api/jsonpdata"></script>

Add routing in app.js

app.get('/api/jsonpdata', (req, res) => {
    
    
  res.send('callback("hello jsonp")');
});

In this way, if you get the string from the server and conform to the js syntax, you can get the data, execute the callback function, and then print it out in the console.

Insert picture description here

The server can pass parameters through get url and dynamically splice out various data to return to the client.

2.CORS server support

CORS is a W3C standard, the full name is "Cross-origin resource sharing" (Cross-origin resource sharing). It allows browsers to issue XMLHttpRequest requests to cross-origin servers, thus overcoming the limitation that AJAX can only be used from the same source.

The entire CORS communication process is automatically completed by the browser without user involvement.

For simple requests

For simple requests, the browser directly issues CORS requests. Specifically, it is in the request header information, the addition of a Originfield.

OriginThe field is used to indicate which source this request comes from (protocol + domain name + port). The server compares Access-Control-Allow-Originand decides whether to agree to this request based on this value .

If the domain name specified by Origin is within the permitted range, the response returned by the server will contain several more header fields Access-Control-XXXX

Insert picture description here

For non-simple requests

Non-simple requests are those that have special requirements for the server, such as the request method is PUT or DELETE, or the type of the Content-Type field is application/json.

For non-simple CORS requests, an HTTP query request will be added before the formal communication, called " pre-request "-the browser first asks the server whether the domain name of the current web page is in the server's permission list. The browser will send a formal XMLHttpRequest request only if it gets a positive answer, otherwise it will report an error.

Backend modification

We modify the backend app.js

app.all('*', function (req, res, next) {
    
    
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, DELETE, OPTIONS')
  next();
});

The response header will naturally have an extra part

Insert picture description here

We changed the previous /api/test to the put method request, and the front end also modified the put.

We refresh the page, open F12, and find that there are four requests, namely to get html documents, load js files and two test requests

Insert picture description here

Because this is a non-simple request, the first of which is an OPTIONS request.

Insert picture description here

The second request is the formal PUT request

Once the server passes the "pre-check" request, it will be the same as a simple request, with an Origin header field. The server's response will also have an Access-Control-Allow-Origin header field.

Insert picture description here

Illustration: Firefox rejection, the first request for options 200, the second request was not sent

Insert picture description here

Insert picture description here

note

It should be noted that if you want to send a cookie, Access-Control-Allow-Origin cannot be set as an asterisk*, you must specify a clear domain name consistent with the requested webpage.

3.HTTP代理(http proxy)

We usually use webpack's devServer.proxy to implement cross-domain. The principle is http proxy, which sends all ajax requests to the devServer server, and then forwards them to the data interface server by the devServer server.

Reference materials:

Guess you like

Origin blog.csdn.net/weixin_43792004/article/details/112913077