天天看點

HTTP中POST送出資料的四種方式詳解

作者:HelloWorld開發者社群

HTTP中POST送出資料的四種方式詳解

首先說一下為什麼寫這篇文章,以前寫用戶端的時候,要經常調用後端的接口,一般很多公司的接口,都是統一POST送出方式

服務端響應的是 JSON 格式字元串,友善統一管理,當時對POST不太清楚,開始的時候,不覺得有啥

但是真正等到自己寫一個獨立的技術社群的時候,也就是 www.helloworld.net ,需要上傳,需要表單送出等

才發現,不懂這些,用到了的時候,很是費勁,很耽誤時間。

下面就當是複習了,學習一下GET , POST 這兩種最常用的送出方式

HTTP送出方式有哪些?

HTTP 請求方法有9種,分别是

序号 方法 描述
1 GET 請求指定的頁面資訊,并傳回實體主體。
2 HEAD 類似于 GET 請求,隻不過傳回的響應中沒有具體的内容,用于擷取報頭
3 POST 向指定資源送出資料進行處理請求(例如送出表單或者上傳檔案)。資料被包含在請求體中。POST 請求可能會導緻新的資源的建立和/或已有資源的修改。
4 PUT 從用戶端向伺服器傳送的資料取代指定的文檔的内容。
5 DELETE 請求伺服器删除指定的頁面。
6 CONNECT HTTP/1.1 協定中預留給能夠将連接配接改為管道方式的代理伺服器。
7 OPTIONS 允許用戶端檢視伺服器的性能。
8 TRACE 回顯伺服器收到的請求,主要用于測試或診斷。
9 PATCH 是對 PUT 方法的補充,用來對已知資源進行局部更新 。

最常用的還是 GET , POST

HTTP的組成部分

我們知道,http是一個通信協定,啥叫通信協定,通信嘛,就是兩個人要溝通,協定嘛,就是怎麼溝通

比如我說A,你知道我餓了想吃東西了,我再說 A 米飯, 你就知道我餓了,并且想吃米飯了。

對的,協定就是雙方提前商量好的溝通的内容的格式

HTTP通信協定就是 HTTP用戶端和HTTP服務端 雙方規定好的格式

那麼這個HTTP消息,有哪幾部分組成呢

很簡單,HTTP消息包含兩部分

  • 請求頭
  • 請求體

比如我們在浏覽器中發一個請求www.helloworld.net 回車,此時我們發的是GET請求

那麼請求頭是:

GET / HTTP/2
Host: www.helloworld.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: Hm_lvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406379; Hm_lpvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406379
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
If-None-Match: "d696-1nnZwKI6/LZalqvEzQx9IFil/tw"
TE: trailers           

注意: HTTP 的GET請求,是沒有請求體的,這也就是為什麼有些公司統一封裝請求為POST,而不是GET的原因了

因為POST是有請求體的,可以帶大量的資料,GET因為沒有請求體,攜帶參數隻能放在URL中,能帶的資料量是比較少的。

GET 請求方法

GET 訪求方法最常用,也是最簡單的一種,像其語義一樣,GET 就是擷取檔案的意思

是以GET請求就是擷取伺服器上的某個資源 ,使用也很簡單,我們記住下面兩點就行了

  • GET 傳參數隻能在url後面帶上參數,比如 http://www.helloworld.net?name=tom&age=23

伺服器收到請求就可以解析出來url後面帶的參數了,name = tom , age = 23

  • 還有一點,很少有人說,就是上面我們說的,GET請求是沒有請求體的

下面我們重點看一下POST請求

POST 請求方法

POST 是送出的意思,如果我們需要向伺服器送出一些資料,就可以使用POST方法

雖然POST是送出的意思,協定規定的也是用POST送出資料,但是現在很多公司并沒有這樣搞

查詢也會用POST,其實它隻是個單詞,服務端收到 請求後,是查詢資源,還是删除資源,還是送出

都可以的,隻是看你們公司前後端怎麼規定即可。

下面我們看看POST有哪幾種送出資料的方式

第一種application/x-www-form-urlencoded

這也是POST預設的一種方式 ,對應的請求頭中的 Content-Type 為 application/x-www-form-urlencoded

我們從浏覽器中抓取www.helloworld.net 上的幾個請求方式,為例,如下

## 請求頭
POST /v1/special/getSpecialCateList HTTP/2
Host: tiger-api.helloworld.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Authorization: 
token: 
ts: 1668407094
sign: d41d8cd98f00b204e9800998ecf8427e
deviceType: pc
Origin: https://www.helloworld.net
Connection: keep-alive
Referer: https://www.helloworld.net/
Cookie: Hm_lvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406379; Hm_lpvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406398
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Content-Length: 0

## 請求體
action=10&pageNum=1&pageSize=10&uuid=15139897           

此種方式,一般是送出key, value 的值。

第二種:multipart/form-data

我之前把這種當作了上面的那種,後來寫檔案上傳的時候,查了一下,原來 不是

這種送出方法一般是上傳檔案用的多。通常是用在用戶端向服務端傳送大檔案資料,如:圖檔或者檔案。

首先來解釋下什麼它的編碼方式,首先會生成一個很長的 boundary 字元串分界線,表明下面的都是表單内容,然後緊接着跟的是表單中的第一個鍵值對中的名稱,而後一個換行,跟着值。然後再生成一個boundary 字元串分界線,用于分割不同的鍵值。之後就重複以上操作,詳細的流程請看下方的例子。

同樣我們以 www.helloworld.net 舉例,我們從裡面找個接口,抓取一下,看看

# 請求頭
POST http://www.helloworld.net/xyz HTTP/1.1
Host: www.helloworld.net
User-Agent: python-requests/2.24.0
Accept-Encoding: gzip, deflate
Accept: */*
Content-Type: multipart/form-data; boundary=e42346452as650adf2345fadade
Content-Length: 222
Connection: keep-alive

# 請求體
--e42346452as650adf2345fadade
Content-Disposition: form-data; name="field0"

value1
--e42346452as650adf2345fadade
Content-Disposition: form-data; name="field1"

value2
--e42346452as650adf2345fadade--
Content-Disposition: form-data; name="field2"; filename="filename"
Content-Type: text/plain

--e42346452as650adf2345fadade--           

從上面我們可以知道,在請求頭中的 Content-Type中,有一個 boundary=e42346452as650adf2345fadade

這個boundary後面的字元串都是随機生成的。用于請求體中資料的分段的。

其實就是個分隔符的作用。

第三種:application/json

這種就是我們現在用的最多的了,而且也非常友善

在請求頭中設定 content-type=application/json,就表明請求體中的内容格式為json格式

同樣的,服務端在響應的時候,順應頭中也會添加一個 content-type=application/json

同樣的也是告訴用戶端,我響應給你的響應體中的内容,格式同樣為 json 格式

同的樣我們也參照 www.helloworld.net 中的一個請求,如下

## 請求頭
POST /v1/special/getSpecialList HTTP/2
Host: tiger-api.helloworld.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/json
Authorization: 
token: 
ts: 1668408188
sign: 08fab32346193fa92037b5ca5f9ed592
deviceType: pc
Content-Length: 30
Origin: https://www.helloworld.net
Connection: keep-alive
Referer: https://www.helloworld.net/
Cookie: Hm_lvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406379,1668408042,1668408051; Hm_lpvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668408051
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
TE: trailers

## 請求體
action=10&pageNum=1&sortType=0           

我們看一下響應體:

{
  "code": 1,
  "data": {
    "hasMore": false,
    "list": [
      {
        "uuid": "5441523000",
        "title": "區塊鍊原理和應用",
        "totalCount": 0,
        "chapterCount": 1,
        "readCount": 0,
        "subscribeCount": 1,
        "createTime": "0001-01-01T00:00:00Z",
        "status": 0,
        "profile": "1037883613",
        "nicker": "小天",
        "avatar": "https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/d04d513fbea19f6cb7c3b4beee3c7f5e.jfif",
        "subscribed": false
      },
      {
        "uuid": "bbatgp",
        "title": "C語言程式設計(初級)",
        "totalCount": 0,
        "chapterCount": 19,
        "readCount": 2938,
        "subscribeCount": 1,
        "createTime": "0001-01-01T00:00:00Z",
        "status": 0,
        "profile": "80662724",
        "nicker": "Suzhou",
        "avatar": "https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/d04d513fbea19f6cb7c3b4beee3c7f5e.jfif",
        "subscribed": false
      }
    ]
  },
  "message": "擷取資料成功",
  "errMessage": ""
}           

第四種:text/xml

這個一直沒有遇到過,很少用

其實就是請求消息中,請求體中的内容格式是純文字xml格式

此種我們就不作介紹

有興趣的可以下面自己查資料

綜上所述,HTTP 的POST四種方法以及GET的簡單介紹,我們總結如下:

  • GET請求隻能在URL中攜帶參數,别說請求頭中也能帶參數,請求頭中帶參數,是所有的方法都可以的,不算是GET方法的
  • GET請求是沒有請求體的
  • POST送出資料有四種方式,分别如下:
1. `application/x-www-form-urlencoded` , 也是預設的方式,主要送出的資料是key, value 形式的
  2. `multipart/form-data` ,此種方式 是用戶端向服務端送出大資料用的,一般上傳檔案等用到。           

​ 注意這種方式,會在請求頭中生成一個boundary字段,其對應的值是一個随機生成的字元串,用于分隔請求體中的資料用的

  1. application/json 此種方式,用的最多,也是最常用的方式,不過我在寫www.helloworld.net的過程中,很少用這種方式
  2. 因為這種方式有一個缺點,就是服務端在解析的時候,需要建立大量的結構體或者類。是以最後選擇了第一種的送出方式
  3. text/xml 這種就不怎麼用了,請求體中是xml格式

簡單的介紹了一下HTTP的GET,POST的一些知識,希望對你們有用。

繼續閱讀