preface

The purpose of this article is to record the process of self-doubt, such as

  1. In the Chrome debugger,Form DataRequest PayloadWhat’s the difference?
  2. application/x-www-form-urlencodedapplication/jsonWhat’s the difference? How should we choose in development?
  3. Why does the back end sometimes fail to parse the data it sends?
  4. inPOSTFor cross-domain requests, there is a way not to sendOPTIONSCan precheck requests also send data?

Without further ado, get right to the point.

Find a problem and start with two screenshots

These two screenshots are the original intention of writing this article. When opening the wechat article, the Form Data is displayed. The second picture shows the Request sent by Nuggets when opening the article. Why are all POST requests, but there are two ways to send data?

I’m one of those people who can’t sleep until we figure this out, so let’s just re-enact it locally and get a good look at these two.

If you don’t want to see the analysis in the middle, you can just click on the summary to see Jay.

The scene again

The two services, the front end and the back end, were used locally to transfer data by creating an XMLHttpRequest object and changing the Content-Type by setRequestHeader(). We ended up recreating the two modes perfectly in the debugging tool.

The sample code in the article can be found from this warehouse, want to try their own partners can click to view the details of the sample address.

git clone -b demo/study-post-request https://github.com/jsjzh/tiny-codes.git
Copy the code

Request Payload

If you want to see the Request Payload, you need to set the Request header Content-Type: application/json, and then serialize the data through json. stringify and send it.

You can see me here’s Origin: http://localhost.charlesproxy.com:3000, this is because the local package with Charles, have to do this one agent

Capture package directly on the screen shot

The top half is the complete HTTP request, with the header above the empty line and the body below the empty line. As you can see, our request body is a JSON serialized string.

In the second half, note the JSON TAB and JSON Text TAB. This TAB is automatically added by Charles after we set content-Type: application/ JSON.

Parse: content-Type: application/json The request body is a JSON string and can be parsed using json.parse.

The data sent is

{
  "name": "king"."age": 18."isAdmain": true."groups": [1.2.3]."address": ""."foo": null."bar": undefined,
  "extra": { "wechat": "kimimi_king"."qq": 454075623}}Copy the code

The parsed data is

{
  "name": "king"."age": 18."isAdmain": true."groups": [1.2.3]."address": ""."foo": null."extra": { "wechat": "kimimi_king"."qq": 454075623}}Copy the code

(bar: undefined, number, Boolean, and null);

Form Data

For Form Data, we need to set Content-Type: Application/X-ww-form-urlencoded, and then send the Data through Qs.stringify serialization.

Qs is the QS NPM Source, which is a library to querystring data

He can convert an object into something like a GET request, right? The query field key=data&key2= datA2

If you send it directly without qs processing, the method will use toString() to convert the data to a string. If you pass an object, you will get [Object Object].

Here also directly posted the capture package screenshots

The top half is the HTTP request, you can see that when we set Content-Type: Application/X-www-form-urlencoded the request body is also placed after the blank line.

Json and JSON Text tabs have been replaced by Form tabs.

After receiving the HTTP request, the back end is also the request body after the truncated empty line, and is parsed using Qs.parse.

The data sent is

{
  "name": "king"."age": 18."isAdmain": true."groups": [1.2.3]."address": ""."foo": null."bar": undefined,
  "extra": { "wechat": "kimimi_king"."qq": 454075623}}Copy the code

The parsed data is

{
  "name": "king"."age": "18"."isAdmain": "true"."groups": ["1"."2"."3"]."address": ""."foo": ""."extra": { "wechat": "kimimi_king"."qq": "454075623"}}Copy the code

When compared with content-Type: application/json, we can see that not only are the number and Boolean data types missing, but foo: null is also converted to foo: “”.

Interchange serialization

We just tried the right content-Type for the right serialization

application/json + JSON.stringify

application/x-www-form-urlencoded + qs.stringify

But as we observed in actual HTTP requests, both of these Content-Types transmit data on empty lines, so we could certainly swap their serialization.

application/json + qs.stringify

To get straight to the conclusion, we set application/json, but use qs.stringify serialization to get the result

  1. Chrome debugger toolRequest PayloadIt cannot be parsed, so it cannot format the data
  2. Charles toolsJSONJSON TextUnable to resolve
  3. Most importantly, if the back end readsContent-Typeapplication/json, will be usedJSON.parseTo parse the data

At the back end we can certainly use Qs.parse by hand, but why should we bury ourselves?

application/x-www-form-urlencoded + JSON.stringify

Similarly, using content-Type and incorrect serialization not only causes Chrome and Charles to fail to parse, but also causes confusion on the back end and, more importantly, creates a hole for themselves.

conclusion

Oh, yeah, I just wanted to skin it

Having said so much, let’s summarize now

  1. Form DataRequest PayloadBecause of the requestContent-TypeDifferent, but different after parsing the request body rendering
  2. Content-TypeSet toapplication/jsonorapplication/x-www-urlencodedIn HTTP requests, exceptHeaderPlace the request body after a blank line

So how should we choose the Content-Type in development? It is recommended to use application/ JSON unless the project specifically requires it, for several reasons

  1. nativeJSON.stringifyJSON.parseNot sweet? Qs has many implementations in the front end, such asqsquery-string, and node’s ownquerystring
  2. x-www-form-urlencodedNeed to use kitsqs.stringify.The data type is lost after the back end parses the data, such asnumber,boolean,null
  3. Different frameworks forqs.parseIn the beginning of the docking project, there may be a front and back end alignment parsing operation
  4. The front endqsThe repository can only handle tier 5 objects by default and can only resolve 1000 parameters by default (both configurations can be modified, of course) to give you an example
{
  "a": {
    "b": {
      "c": {
        "d": {
          "e": {
            "f": {
              "g": { "name": "king" }
            }
          }
        }
      }
    }
  }
}
Copy the code

Because the object has too many nested layers, it is resolved as follows

{
  "a": {
    "b": {
      "c": {
        "d": {
          "e": {
            "[f][g][name]": "king"
          }
        }
      }
    }
  }
}
Copy the code

Of course, using Application/JSON makes a difference

  1. Configure the headContent-Type: application/jsonAnd then instead of a simple request, one will be initiatedOptionsPreview the request
  2. The back-end configuration needs to be synchronizedAccess-Control-Request-Headers: Content-TypeAllows front-end configurationContent-TypeThe head

Of course, going on is the knowledge point of CORS, there are a lot of content can be broken down, I am also sorting out this aspect of the content, you can look forward to a little.

After the language

I wonder if this article has given you any help. I would be honored if it has. When we encounter problems, we can dig deeper, like the Form Data and Request Payload. It is a kind of encapsulation of HTTP protocol by browser, and the correct use of Content-Type is a convention and a standard between us and the backend.

We can certainly set the content-Type as we like, but this requires unnecessary coordination with the back end and is not easy to understand and maintain, so we can keep it simple. Some frameworks will automatically parse the request body based on the value of the content-Type. Let’s not force the game harder.

The footer

Code is life, and I love it.

Technology is constantly changing. Brains are always online. We’ll see you next time

By — Crotch Trio

I am here gayhub@jsjzh welcome to find me to play.

Welcome friends to join me directly, pull you into the group to do things, remember to note where you read the article.

Ps: If the picture is invalid, you can add my wechat: Kimimi_king