三不五時會用到相關的東西, 所以花了點時間查清楚, 本篇重點是參考資料。
用 HTTP 的 POST 的時候, 參數會放在 request body, 然後用 HTTP header Content-Type 決定 request body 編碼方式。
常用的格式 ( Content-Type) 有兩種:
- application/x-www-form-urlencoded: HTML form 的預設值。和 GET 在 URL 後面帶的參數差不多, 用 URL encoding 編碼 (主要差異是空白字元用 '+' 取代), 適合用在簡單的資料。
- multipart/form-data: 適合用在 binary data, 上傳檔案時要改用這個, 比較省空間 (檔案內容不需另外編碼)。
application/x-www-form-urlencoded 用 URL encoding 編碼, 遇到大量 binary 資料時, 資料會變大很多 (可能會到三倍)。若先用 base64 [*1] 編碼再套 URL encoding 會好一些 (變成 4/3 倍), 但還是沒有 multipart/form-data 省。
除了上述的格式也可以用 application/json 或其它格式, 不過得看 web server 是否支援。JSON 不支援 binary data, 所以有 binary data 時要先用 base64 編碼, binary 資料一樣會變 4/3 倍大。雖然 base64 會增加 1/3 倍的資料量, 但它簡單易用, 我個人滿喜歡 base64 的設計。
若目的是要壓縮上傳的文字資料, 除了 application layer 自己壓縮資料外, 也可以在 transport layer 作: 使用 HTTP header Content-Encoding: gzip 然後用 gzip 壓縮 request body [*2]。雖然 response 很常用 Content-Encoding: gzip, 但 request 很少這麼用的樣子, 需要改 web server 設定才能作用。如 apache2: 需另外設定 Input Decompression。
備註
1. 嚴格來說, 要用 base64url (最後兩個 byte 不同), 對 URL encoding 比較安全。Google API 有用這個, 轉換的時候要留意。
2. 另一個選擇是用 Transfer-Encoding: gzip, 這個作法語意比較正確, 但一來實作不如 Content-Encoding: gzip 常見, 二來 Content-Encoding 是 end-to-end, 不用擔心 Proxy 改變內容, 所以還是用 Content-Encoding 較好。
參考資料
POST Content-Type 相關:
- HTML DOM Form enctype Property
- What does enctype='multipart/form-data' mean? 有 multipart/form、application/x-www-form-urlencoded 傳送內容的例子。
- http - application/x-www-form-urlencoded or multipart/form-data?: 前幾個回答都值得看。
Content-Encoding 和 Transfer-Encoding 相關:
- support - Why Content-Encoding gzip rather than Transfer-Encoding gzip - Stack Apps
- http - Transfer-Encoding: gzip vs. Content-Encoding: gzip - Stack Overflow
其它:
- List of HTTP header fields - Wikipedia, the free encyclopedia
- Howto make Nginx decompress a gzipped request: 用 lua 解開 gzip 壓縮的 request body, 可減少 http client 上傳的資料量。
沒有留言:
張貼留言