Preface
This article aims to record the process of solving puzzles, such as
- In the chrome debugging tool, what is the difference between
Form Data
andRequest Payload
- What is the difference between
application/x-www-form-urlencoded
andapplication/json
How should we choose during development? - Why does the backend sometimes fail to parse the data sent by itself?
- In the cross-domain request of
POST
OPTIONS
pre-check request?
Not much to say, go directly to the topic.
Found the problem, start with two screenshots
These two screenshots are the original intention of writing this article. When the WeChat article is opened, Form Data
is displayed. The second picture is a request initiated by the Nuggets when opening the article. At the time, it was very strange to see them, Form Data
and Request Payload
What's the difference? Why are POST
requests, but there are two ways to send data?
I belong to the person who encounters this kind of strange problem and can't sleep without getting him clear. Let's reproduce it directly in the local scene and take a good look at these two goods.
If you don’t want to see the analysis process in the middle, you can directly click summary to see Jay.
Scene reproduction
We started two services locally, front-end and back-end, by creating XMLHttpRequest
objects for data transmission, and using setRequestHeader()
to change Content-Type
, and finally we reproduced the two modes perfectly in the debugging tool.
The sample code in the article can be found in this warehouse. who hope to try it themselves can click to view the details 160a1d538489e2 sample address .
git clone -b demo/study-post-request https://github.com/jsjzh/tiny-codes.git
Request Payload
If you want to see Request Payload
, you need to set the request header Content-Type: application/json
, and then send the data after serialization of JSON.stringify
You can see my Origin: http://localhost.charlesproxy.com:3000
here. This is because Charles needs to be used to capture local packets, and this is used as a proxy
Directly upload the screenshot of the package
The upper part is a complete http request. Above the blank line is the request header, and below the blank line is the request body. You can see that our request body is a json serialized string.
In the lower part, pay attention to the two tabs JSON
and JSON Text
Content-Type: application/json
, Charles will automatically bring them.
After the backend receives the http request, it is the parsing of the request body after intercepting the blank line. Because we passed Content-Type: application/json
, the backend knows that the request body is a json string, so it can be parsed 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 }
}
The parsed data is
{
"name": "king",
"age": 18,
"isAdmain": true,
"groups": [1, 2, 3],
"address": "",
"foo": null,
"extra": { "wechat": "kimimi_king", "qq": 454075623 }
}
It can be seen that in addition to bar: undefined
, number
, boolean
and null
, the data types are all correctly transmitted.
Form Data
Let's talk about Form Data
, we need to set Content-Type: application/x-www-form-urlencoded
, and then qs.stringify
before sending.
qs is qs npm source , which is a library for querystring dataIt can be simply understood that he can convert an object into a similar get request? The following query field
key=data&key2=data2
If you send directly without qs processing, the method will use
toString()
to convert the data to a string. If you are transmitting an object, you will get[object Object]
The screenshot of the packet capture is also posted directly here
The upper part is the http request. You can see that when we set Content-Type: application/x-www-form-urlencoded
request body is also placed after the blank line.
In the lower part, compare the application/json
just now to find the difference. JSON
and JSON Text
are gone, replaced by Form
tabs.
After the backend receives the http request, it also intercepts the request body after the blank line, and uses qs.parse
for parsing.
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 }
}
The parsed data is
{
"name": "king",
"age": "18",
"isAdmain": "true",
"groups": ["1", "2", "3"],
"address": "",
"foo": "",
"extra": { "wechat": "kimimi_king", "qq": "454075623" }
}
After Content-Type: application/json
, we can see that not only the data types of number
and boolean
foo: null
also been converted to foo: ""
.
Exchange serialization method
Just now we tried the correct Content-Type
corresponding to the correct serialization method
application/json
+ JSON.stringify
application/x-www-form-urlencoded
+ qs.stringify
But in fact, we observed the actual http request, these two Content-Type
are transmitted after the data is placed in a blank line, so of course we can also exchange their serialization methods.
application/json + qs.stringify
Here is the conclusion directly, we set application/json
, but use qs.stringify
serialization, the result is
Request Payload
chrome debugging tool cannot be parsed, so the data cannot be formattedJSON
andJSON Text
charles tool cannot be parsed- Most importantly, if the backend reads
Content-Type
asapplication/json
, it will useJSON.parse
to parse the data
Of course we can manually use qs.parse
for analysis in the backend, but why should we bury ourselves?
application/x-www-form-urlencoded + JSON.stringify
In the same way, using Content-Type
and incorrect serialization methods, not only chrome and charles cannot be parsed, but also the backend will have doubts, and more importantly, it will bury itself.
to sum up
Oh, yes, I just want to skin it
So much has been said before, now let’s summarize
Form Data
andRequest Payload
are because the requestedContent-Type
different, and different presentation methods after parsing the request bodyContent-Type
set toapplication/json
orapplication/x-www-urlencoded
In the http request,Header
, the request body is placed after the blank line
Then how should we choose Content-Type
in development? application/json
if it is not a special requirement of the project. The reasons are as follows
JSON.stringify
native 060a1d53848f3f andJSON.parse
not fragrant? There are many implementations of qs in the front end, such asqs
andquery-string
, and node's ownquerystring
x-www-form-urlencoded
needs to use the supportingqs.stringify
, backend parsing data will lose the data type , such asnumber
,boolean
,null
- Different frameworks have
qs.parse
. There may be front-end and back-end alignment operations when the project is first docked. - The front-end
qs
warehouse can only handle 5 layers of objects by default, and can only parse 1000 parameters by default (of course, both configurations can be modified), for example
{
"a": {
"b": {
"c": {
"d": {
"e": {
"f": {
"g": { "name": "king" }
}
}
}
}
}
}
}
Because the number of nested objects is too deep, it becomes as follows after parsing
{
"a": {
"b": {
"c": {
"d": {
"e": {
"[f][g][name]": "king"
}
}
}
}
}
}
Of course, application/json
, it will be a little different
- After configuring the header
Content-Type: application/json
, it is not a simple request. AOptions
pre-check request will be initiated. - The back end needs to be configured with
Access-Control-Request-Headers: Content-Type
synchronously, and the front end is allowed to configure theContent-Type
head
Of course, CORS
's talk about the knowledge points of 060a1d53849081. There are also many contents in this area that can be broken down and detailed. I am also sorting out the contents in this area, so I can look forward to it.
Afterword
I don’t know if this article has brought you some help. If so, it’s my honor. When you encounter problems, you can dig deeper, like this time Form Data
and Request Payload
. When we dig into At the http request level, we can find that there is no difference between the two. It is a kind of encapsulation of the http protocol by the browser, and the correct use of Content-Type
is an agreement between us and the back-end joint debugging, and it is also a specification.
Of course, we can set Content-Type
, but this requires unnecessary joint debugging with the backend, and it is not convenient for subsequent understanding and maintenance, so we can keep it simple, some frameworks will automatically parse the request body and hair Content-Type
Since there are so few, we should not forcefully increase the difficulty of the game.
Footer
Code is life, and I am happy with it.
Technology is constantly changing
Mind is always online
The front end is long
See you next timeby --- Crotch Trio
I am here gayhub@jsjzh welcome everyone to come and play with me.
Welcome friends to add me directly, pull you into the group and do things together, remember to note where you saw the article.
ps: If the picture is invalid, you can add me wechat: kimimi_king
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。