HTTP is familiar, but many of the details of HTTP are not, and this article will discuss some important points that are easily overlooked.

First, how do you write a GET request in native JS? The following code takes only 3 lines:

let xhr = new XMLHttpRequest();
xhr.open("GET"."/list");
xhr.send();
Copy the code

Xhr. open takes the request method as the first argument, and the url as the second argument, and sends it.

If you need to add a request parameter, it would look like this if you are using jQuery ajax:

$.ajax({
    url: "/list",
    data: {
        page: 5
    }
});Copy the code

The second argument to open is spelled above the request URL if it is used native:

And the parameters need to be escaped, as shown in the following code:

function ajax (url, data) {
    let args = [];
    for (let key inData) {// Arguments need to be escaped args.push('${encodeURIComponent(key)} = 
                                     ${encodeURIComponent(data[key])}`);
    }
    let search = args.join("&"); // Check whether the current url has a parameter url += ~ url.indexof ("?") ? `&${search}` : `?${search}`;

    let xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.send();
}Copy the code

So why not with JQ? Since JQ does this for us, JQ’s Ajax supports a parameter called processData, which defaults to true:

$.ajax({
    url: "/list",
    data: {
        page: 5
    },
    processData: true
});
Copy the code

This parameter is used to process incoming data, as shown in the jQ source code:

If data is passed, processData is true, and data is no longer a string, param is called to processData. Let’s look at how the param function is implemented:

As you can see, it is also similar to my own Ajax implementation, where key and value escapes are concatenated with “=”, then pushed into an array, and finally joined. The difference is that its logic is more complex than mine, and it calls a buildParams function to handle key/value, because value can be an array or an Object. If value is an Object, then direct encode will become an escape of “[Object Object]” :

So buildParams determines whether the current value is an array or Object when it processes each key/value, as shown in the following figure:

If it is an array, each element of the array becomes a separate request field, and its key is the parent key, which is combined with the array index, as in {ids: Ids [0]=1, IDS [1] = 2, IDS [2] = 3, ids[2] = 3 “Yin “}} would be spelled as: user[id]=1333, user[name]= Yin, otherwise it would be considered a simple type, just call param add and push it to the array s. So we’re doing a recursive call, we’re going to keep putting together the key until the value is a normal variable, and then we’re going to get to the else logic at the end.

That is, the following code:

$.ajax({
    url: "/list",
    data: {
        user: {
            name: "yin",
            age: 18
        }
    },
});Copy the code

The url that will be spelt is:

/list? user[name]=yin&user[age]=18

Note that the brackets above have not been escaped. And if it’s an array:

$.ajax({
    url: "/list",
    data: {
        ids: [1, 2, 3]
    },
});Copy the code

The spelt request URL is:

/list? ids[0]=1&ids[1]=2&ids[2]=3

If you use Java’s Spring MVC framework on the back end and understand this format, the framework receives an Array of such parameters and passes it to the business code, which doesn’t care what to do with such parameters. Other frameworks should be similar.


How do I write a POST request with native JS? As shown below:

The parameters of the POST request are not placed in the URL, but in the send, the body of the request. You might ask: Can’t you just put urls? I’m going to put the URL. Well, if you can be capricious, yes, if the HTTP framework that the backend is using can fetch data from the URL, because it’s bound to get the URL, it’s bound to get the body of the request, so depending on what it wants to do, according to the HTTP standard, if the request is POST, then it’s bound to get the body of the request, It’s not going to be in search of the URL, but of course it can be changed to take both of them.

Then we’ll see that the mime type of the request is text/plain:

And when viewing the request parameters, it is not usual to see them displayed line by field:

Why is that? This is because we didn’t set its Content-Type, as follows:

let xhr = new XMLHttpRequest();
xhr.open("POST"."/add");
xhr.setRequestHeader("Content-type"."application/x-www-form-urlencoded");
xhr.send("id=5&name=yin");Copy the code

If the content-type is x-www-form-urlencoded, Chrome will also display the field lines when checking:

This is also jQ’s default content-type:

It is one of the most common request encoding methods. It supports GET/POST and other methods. All data is changed to the form key1=value1&key2=value2, and special characters need to be escaped to UTF-8 numbers, such as Spaces will become %20:

Since Chinese takes up three bytes in UTF-8, it has three % symbols.


We just said xhr.send a string. What if we send an Object? The following code looks like this:

let xhr = new XMLHttpRequest();
xhr.open("POST"."/add");
xhr.send({id:5, name: "yin"});Copy the code

When checking the console, it looks like this:

In other words, you are actually calling the toString method of Object. So you can see that the data in send needs to be converted to a string.

In addition to strings, send supports FormData/Blob formats, such as:

let form = $("form") [0]; xhr.send(new FormData(form));Copy the code

But it ends up being sent as a string.


Let’s take a look at other request formats, such as Github’s REST API, which uses JSON to send requests:

If you specify the content-type as application/json, then stringify the send data:

let xhr = new XMLHttpRequest();
xhr.open("POST"."/add");
xhr.setRequestHeader("Content-type"."application/json");
let data = {id:5, name: "yin"};
xhr.send(JSON.stringify(data));Copy the code

If you are using JQ, you can do this:

$.ajax({
    processData: false,
    data: JSON.stringify(data),
    contentType: "application/json"
});
Copy the code

ProcessData is false, telling JQ not to process the data — that is, to spell key1= Value1 &key2= Value2 and simply send the data to it.

We can compare the advantages and disadvantages of JSON and Urlencoded. The disadvantage of JSON is that the workload of parse is significantly higher than that of split(“&”), but the advantage of JSON is that it is simpler to express complex structures. For example, a two-dimensional array (M * n) in Urlencoded needs to be split into M * N fields, while JSON does not. Therefore, if the request data structure is relatively simple, it will be advantageous to use the commonly used Urlencoded data structure, while when the request data structure is more complex, it will be advantageous to use JSON. In general, urlencoded is often used.


A third common encoding is multipart/form-data, which can also be used to send requests, as shown in the following code:

let formData = new FormData();
formData.append("id", 5); // The number 5 is immediately converted to a string"5"
formData.append("name"."#yin");
// formData.append("file", input.files[0]);
let xhr = new XMLHttpRequest();
xhr.open("POST"."/add");
xhr.send(formData);Copy the code

It is usually used for uploading files, which must be in this format. The code above sends something like this:

Each field is separated by a random string to ensure that the string does not appear in the sent content, so that the sent content does not need to be escaped, because if the file is large, escaping takes considerable time and can grow exponentially in size.


Then we will discuss another question. We know that when we input a url request data in the browser address bar, this time is a GET request, and the GET request we send in the code with Ajax is also A GET request. Is there any difference between the GET of the browser accessing the URL and the GET of Ajax?

In order to be able to observe the GET issued by the browser itself, you need to use a packet capture tool to see what the GET looks like, as shown below:

An obvious feature of the browser’s own GET is that it sets the Accept field in the HTTP request header and places text/ HTML first, meaning that it wants to receive HTML. The dynamic Ajax capture display looks like this:

As you can see, get requests accessed using the address bar are essentially the same as get requests accessed using Ajax, except that with Ajax we can set the HTTP request header, whereas with address bar access the browser adds the default request header.


The above is to use HTTP grab bag, we can see a complete url of the request, including the parameters of the request, and if it is to grasp the HTTPS package, GET on the url parameter can’t see the:

That is, HTTPS request packets, including request URIs, are encrypted and can be viewed only after decryption. Does that mean that GET using HTTPS is also secure, and POST using HTTPS is not more secure than GET?

Let’s take a look at the HTTP request message, as shown below:

If you use the packet capture tool, you can see that the request packets are indeed arranged in the figure above, as shown in GET:

The POST looks like this:

So essentially GET/POST is the same thing, except GET puts the data into the URL, and POST puts the data into the request body. In addition, urls are limited in length, including the browser and the receiving service such as Nginx, while the request body is unlimited (browsers are not limited, but nginx generally is limited), and POST data can be encoded in a variety of formats.

However, POST is more secure than GET for the following reasons:

  1. The GET parameter is placed on top of the URL and can be saved by the user as a bookmark, propagating links, or exposing sensitive data, such as a login password
  2. If the search engine’s request to modify the database supports GET while crawling the site, it is likely that the database will be unintentionally modified by the search engine
  3. Tags such as script/img are GET requests, which are more convenient for cross-site request forgery. Entering the browser address bar is also GET, which facilitates the modification of requests


The request response status code is then discussed. Most people know about 200, 404, and 500, but not the rest. Here I list some of the commonly used status codes.

1. 301 Permanent transfer

If you want to change your domain name to 301, you can use nginx to return to 301. If you want to change your domain name to www.renfed.com, you can use nginx to return to 301.

server {
    listen       80;
    server_name  www.rrfed.com;
    root         /home/fed/wordpress;
    return       301 https://www.rrfed.com$request_uri;
}Copy the code

When the browser receives 301, it automatically jumps. If a search engine finds 301 when crawling, it will change the domain name of the page after a few days.

In another scenario, if you want to automatically redirect to HTTPS when accessing HTTP, you can also use 301, because if you directly enter the domain name in the browser address bar and press Enter, there is no HTTPS in front of it, then it is the default HTTP protocol. At this time, we want users to access secure HTTPS, not HTTP. So to make a redirect, you can also use 301, for example:

server {
    listen       80; 
    server_name  www.rrfed.com;

    if ($scheme! ="https") {
         return 301 https://$host$request_uri; }}Copy the code

2. 302 Found Resources are temporarily transferred

Many short links jump to long links using 302, as shown below:

3. It has Not been Modified

If the js/ CSS file is not changed when the webpack-dev-server is developed locally, then the local JS/CSS file will be returned when the page is refreshed, as shown in the following figure:

How does the webpack-dev-server service know that it is not modified, because the browser carries an etag when requesting it, such as:

W/”10e632-Oz38I6asQyS459XpsaJYkjMUoZI”

The service calculates the eTAG of the current file, which is the hash value of a file, and compares the etags passed to it. If they are equal, 304 is returned as unchanged. If any changes are made, 200 and the contents of the file will be returned and a new etag will be given to the browser. The browser will carry the new eTag the next time it requests it. If you turn disable cached on the console, the browser will not carry eTag, even if it has it. Another field to check for changes is Last Modified Time, which is based on when the file was Modified.

400 Bad Request The Request is invalid

When necessary parameters are missing and the format of the parameter is not correct, the back end usually returns 400, as shown in the following figure:

Along with the message:

{“message”:”opportunityId type mismatch required type ‘long’ “}

400 indicates that the request parameter is incorrect, and the message is displayed indicating that a number, not a string, is required.

5. Forbidden Forbidden service

The service understands your request, including the correct input, but refuses to provide service. For example, the service allows direct access to static files:

But do not allow access to a directory:

Otherwise, people will have full access to the files on your server.

The difference between 403 and 401 is that 401 has no authentication, no login authentication and so on.

6. 500 Internal server error

If the business code fails to catch an exception and is caught by Tomcat, 500 errors will be returned:

For example, the database field length is limited to 30 characters. If a record of 31 characters is directly inserted without judgment, it will cause the database to throw an exception. If the exception is not captured and processed, it will directly return 500.

When the service is completely down and there is no return, it is 502.

7. 502 Bad Gateway The Gateway is faulty

As shown below:

This is because nginx received a request but the request was not called, either because the business service hung up or because the port number was incorrectly written:

server {
    location / {
        # Webpack servicesProxy_pass https://127.0.0.1:7071; }}Copy the code

Nginx returns 502.

8. 504 Gateway Timeout The Gateway times out

For example, the default maximum time for PHP service to process request response is 30s. If the time exceeds 30s, it will hang up and return 504, as shown in the following figure:

This may be because the service also requests the service of a third party, which takes a long time to process and does not return. For example, when sending Push requests to FCM, if a request requires too much subscriptions from browsers, it will often be processed for a long time, resulting in 504.

9. 101 Protocol conversion

Websocket is upgraded from HTTP. Before establishing a connection, you need to upgrade the protocol through HTTP:

There is also a 600, a less common status code that indicates that the server does not return the response header, but only the physical content.

The status code is actually a number and can be returned arbitrarily, but it is best to return the appropriate status code as specified by HTTP. If you return an HTTP status code starting with 4, 5, or 6, the browser will print an error indicating that the current request failed.


We haven’t said how to tell if the request was successful, as shown in the following code:

xhr.open("POST", UPLOAD_URL);
xhr.onreadystatechange = function() {// readyState is 4 to indicate that the request is completeif (this.readyState === 4){
        if (this.status === 200) {
            let response = JSON.parse(this.responseText);
            if(! response.status || response.status.code ! == 0) {// failed callback.failed && callback.failed(); }elseCallback. Success (response.data.url); }}else if(enclosing the status > = 400 | | this. The status = = = 0) {/ / failure callback failed && callback. The failed (); // Normal should not return more than 20 status code, this case is also considered failure}else{ callback.failed && callback.failed(); }}}; xhr.send(formData);Copy the code

Here’s a question: If the status code returned is a redirection starting with 3, do I need to send another request myself?

As it turns out, the browser automatically redirects you, as shown below:


Finally, three commonly used request codes are mentioned in this paper, which are Application /www-x-form-urlencoded, Application/JSON, multipart/form-data. The first is the most commonly used one, which is suitable for GET/POST, etc. The second data format is commonly used for request responses, and the third is commonly used for uploading files. Then it compares POST and GET. Although the request data of both are in HTTP packets, but in different positions, POST is still more secure than GET considering the usage scenarios of users and search engines. Finally, several commonly used HTTP status codes are mentioned, and some practical examples are used to deepen the impression and understanding.