preface
The purpose of this article is to record the process of self-doubt, such as
- In the Chrome debugger,
Form Data
和Request Payload
What’s the difference? application/x-www-form-urlencoded
和application/json
What’s the difference? How should we choose in development?- Why does the back end sometimes fail to parse the data it sends?
- in
POST
For cross-domain requests, there is a way not to sendOPTIONS
Can 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
- Chrome debugger tool
Request Payload
It cannot be parsed, so it cannot format the data - Charles tools
JSON
和JSON Text
Unable to resolve - Most importantly, if the back end reads
Content-Type
为application/json
, will be usedJSON.parse
To 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
Form Data
和Request Payload
Because of the requestContent-Type
Different, but different after parsing the request body renderingContent-Type
Set toapplication/json
orapplication/x-www-urlencoded
In HTTP requests, exceptHeader
Place 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
- native
JSON.stringify
和JSON.parse
Not sweet? Qs has many implementations in the front end, such asqs
和query-string
, and node’s ownquerystring
x-www-form-urlencoded
Need to use kitsqs.stringify
.The data type is lost after the back end parses the data, such asnumber
,boolean
,null
- Different frameworks for
qs.parse
In the beginning of the docking project, there may be a front and back end alignment parsing operation - The front end
qs
The 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
- Configure the head
Content-Type: application/json
And then instead of a simple request, one will be initiatedOptions
Preview the request - The back-end configuration needs to be synchronized
Access-Control-Request-Headers: Content-Type
Allows front-end configurationContent-Type
The 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