Article Directory
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.XMLHttpRequest
It is widely used in AJAX programming.Use
XMLHttpRequest
to send HTTP requests to achieve data exchange between the website and the server.Send an HTTP request, you need to create an
XHR
object, 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 readyState
the value is changed when the callback
function 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
4.xhr.status
Read-only property
XMLHttpRequest.status
returns the response status code numbers. Error with XMLHttpRequest before the request is completed,status
the value is0
. 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
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
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.
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 Origin
field.
Origin
The field is used to indicate which source this request comes from (protocol + domain name + port). The server compares Access-Control-Allow-Origin
and 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
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
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
Because this is a non-simple request, the first of which is an OPTIONS request.
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.
Illustration: Firefox rejection, the first request for options 200, the second request was not sent
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: