前後端聯調之Form Data與Request Payload,你真的瞭解嗎?
前言
做過前後端聯調的小夥伴,可能有時會遇到一些問題。例如,我明明傳遞資料給後端了,後端為什麼說沒收到呢?這時候可能就會就會有小夥伴陷入迷茫,本文從chrome-dev-tools(F12偵錯程式)中看到的 FormData
與 RequestBody
,給小夥伴們提供一種可能的思路。也給小夥伴們提供一些問題的探究方法。
簡介
什麼是FormData?什麼是RequestPayload?不解釋,直接上圖:
區別?
因為這裡觸及了我的知識盲區,所以有了本文。這個答案是我在 stackoverflow
上得到的。首先還是貼問題,貼答案。
What's the difference between “Request Payload” vs “Form Data” as seen in Chrome dev tools Network tab。
高票回答:
The Request Payload - or to be more precise: payload body of a HTTP Request - is the data normally send by a POST or PUT Request. It's the part after the headers and the CRLF of a HTTP Request.
A request with Content-Type: application/json
may look like this:
POST /some-path HTTP/1.1 Content-Type: application/json { "foo" : "bar", "name" : "John" }
If you submit this per AJAX the browser simply shows you what it is submitting as payload body. That’s all it can do because it has no idea where the data is coming from.
If you submit a HTML-Form with method="POST" and Content-Type: application/x-www-form-urlencoded or Content-Type: multipart/form-data your request may look like this:
POST /some-path HTTP/1.1 Content-Type: application/x-www-form-urlencoded foo=bar&name=John
In this case the form-data is the request payload. Here the Browser knows more: it knows that bar is the value of the input-field foo of the submitted form. And that’s what it is showing to you.
So, they differ in the Content-Type but not in the way data is submitted. In both cases the data is in the message-body. And Chrome distinguishes how the data is presented to you in the Developer Tools.
翻譯過來是說:
Request Payload
更準確的說是 http request的payload body
。一般用在資料通過 POST
請求或者 PUT
請求。它是 HTTP
請求中 空行 的後面那部分。(PS:這裡涉及一個http常被問到的問題,http請求由哪幾部分組成,一般是請求行,請求頭,空行,請求體。payload body應該是對應請求體。)
一個請求伴隨著header設定為 Content-Type: application/json
時候,看起來可能像這樣:
POST /some-path HTTP/1.1 Content-Type: application/json { "foo" : "bar", "name" : "John" }
如果你正常請求一個ajax。瀏覽器會簡單的將你提交的內容作為 payload
展示出來,這就是它所能做的,因為它不知道資料來自哪裡。
如果你提交了一個html表單並且配置上了 method="post"
,並且設定了 Content-Type: application/x-www-form-urlencoded
或者 Content-Type: multipart/form-data
。那麼你的請求可能長這個樣:
POST /some-path HTTP/1.1 Content-Type: application/x-www-form-urlencoded foo=bar&name=John
這裡的 form-data
就是 request payload
。在這裡,瀏覽器知道更多:它知道bar是提交表單的輸入欄位foo的值。這就是它向你展示的。
所以區別就是,他們只是因為 Content-Type
設定的不同,並不是資料提交方式的不同,這兩種提交都會將資料放在 message-body
中。但是chrome瀏覽器的開發者工具會根據這個contentType區分顯示方式。
細節
好了,到這裡我們知道了,其實都是放到了payload中。那麼具體有什麼區別呢?為什麼有時候後端拿不到值呢?這就不得不說對payload的解析方式了。我們以幾個chrome下的測試案例,來理一理這個邏輯。
傳統的Form表單提交
場景構造
<form action="/" method="POST"> <input name="name" type="text"> <input name="password" type="text"> <button>提交</button> </form>
如果我這裡點選提交按鈕,就會觸發瀏覽器的提交功能,那結果是什麼樣呢?
注意點
可以看到 Content-Type
為 application/x-www-form-urlencoded
。
值得形式是以 key1=value1&key2=value2
的形式提交的。
傳統的ajax提交
場景構造
function submit2() { var xhr = new XMLHttpRequest(); xhr.timeout = 3000; var obj = {a: 1, b: 2}; xhr.open('POST', '/'); xhr.send(obj); }
首先我們構造一個簡單的函式,然後觸發它。通過chrome反饋來看:
注意點
1.預設的 Content-Type
為 text/plain
。
2.Request Payload會對非字串做字串轉換。
3.通過 xhr.send(JSON.stringify(obj));
可修正要發的內容
axios方式提交
場景構造
由於axios已經是vue、react的準標配請求方式了,所以這裡探究一下它。
首先我門看axios的文件,當post提交時候可以傳遞什麼型別引數:
注意這個型別,我們分別構造兩個場景。對應它。
function submit3() { var sence1 = 'name=123&val=456'; var sence2 = {name: 123, val: 456}; axios.post('/', sence1) }
分別傳遞字串與物件,提交post請求,然後觀察結果:
場景1——傳遞字串時候的結果:
場景2——傳遞物件的結果:
注意點
1.當我們傳遞字串的時候, Content-Type
自動轉為 xxx-form-xxx
的形式。當為物件的時候,自動轉化為 xxx/json
。
2.字串的時候以 key1=val1&key2=val2
的形式體現,物件以 JSON字串 形式體現。
總結
探索了這麼多種情況之後,那麼我們回顧一下:
Content-Type的差異
1.傳統的ajax請求時候, Content-Type
預設為"文字"型別。
2.傳統的form提交的時候, Content-Type
預設為"Form"型別。
3.axios傳遞字串的時候, Content-Type
預設為"Form"型別。
4.axios傳遞物件的時候, Content-Type
預設為"JSON"型別
Content-Type的值,Form與非Form時,payload的區別。
1.都只支援字串型別(以上探究的幾種情況)
2.Form需要傳遞的格式為 key1=value1&key2=value2
,類似 GET
請求的 QueryString
格式
- 非Form一般為
JSON.stringify(formDataObject)
形式
後端取不到值?
無論何種形式傳遞,後端解析表單資訊的時候,會考慮 Content-Type
。如果是JSON字串的話,後端解析payload的內容時候,肯定要用 JSON.parse(str)
去解析啦。如果是 key1=value1&key2=value2
的形式,則需要去分割字串。
當然這些事情一般後端使用的框架會去處理,但是框架給後端提供取值介面有可能是不同的,所以前端的小夥伴在處理請求問題時,一定要跟後端小夥伴商量好,是用 JSON
還是 FormData
哈。
後記
本來只是小小的一個問題,仔細研究起來發現挺多細節。今天就花時間整理了一下,希望能給大家一些幫助。碼字不容易,如果感到這篇文章對你有用。點個贊,收個藏唄。