python+pytest接口自動化(6)-請求參數格式的確定


我們在做接口測試之前,先需要根據接口文檔或抓包接口數據,搞清楚被測接口的詳細內容,其中就包含請求參數的編碼格式,從而使用對應的參數格式發送請求。例如某個接口規定的請求主體的編碼方式為 application/json,那么在請求該接口時,請求參數格式必須是 json 格式,使用其他的編碼方式請求不會成功。

那么,在http請求中,請求主體常用的編碼方式有哪些?每種編碼方式在python中需要對應使用什么樣格式的請求參數?這便是咱們在本篇博客要弄明白的地方。

content-type

在POST請求中,由content-type指定請求參數的格式,所以,為了搞清楚請求參數的編碼格式,我們有必要了解HTTP請求頭信息中的 content-type 字段。

content-type的作用

在HTTP協議中,報文通常包括兩個部分 請求頭部(head)、請求主體(body),其中 body 可以為空,如 GET 請求是將請求參數放在請求URL中而不是放在 body 中。

而POST請求中的請求參數則是放在 body 中,接收請求的一端(也就是服務器)需要知道傳過來的 body 是什么類型的數據,采用怎樣的編碼方式,才能對數據進行對應的解析,這時就需要在請求頭中使用 content-type 來指明 body 的媒體類型

媒體類型

媒體類型(通常稱為 Multipurpose Internet Mail Extensions 或 MIME 類型 )是一種標准,用來表示文檔、文件或字節流的性質和格式。它在IETF RFC 6838中進行了定義和標准化。

瀏覽器通常使用MIME類型(而不是文件擴展名)來確定如何處理URL,因此Web服務器在響應頭中添加正確的MIME類型非常重要。如果配置不正確,瀏覽器可能會曲解文件內容,網站將無法正常工作,並且下載的文件也會被錯誤處理。

而瀏覽器傳過來的內容也需要指定媒體類型,服務器才能根據媒體類型做對應的數據解析。

常見的媒體類型如下:

另外還有 multipart 類型,表示細分領域的文件類型的種類,經常對應不同的 MIME 類型,用於文件的上傳,分為如下兩種:

multipart/form-data
multipart/byteranges

這里均只做簡單說明,具體每種類型的使用詳情可自行查找相關資料。

總之,在接口測試中,請求頭中的 Content-Type 作用就是,用來告知服務端請求body的編碼方式。GET請求因為body為空,所以在GET請求中沒有Content-Type字段。

get請求參數格式

我們已經知道GET請求的請求參數是直接放在URL中的,且不需要content-type指定媒體類型。而GET請求中的請求參數的編碼格式為query string params。

query string params

說明

query string params 格式,參數會以 url string 的形式進行傳遞,即?后的字符串則為其請求參數,並以&作為分隔符,參數編寫方式為?key=value&key=value,拼接在 url 后面。通常用於GET請求,除此之外其他有些請求方式也可以使用這種格式。

在瀏覽器中打開百度,搜索給你一頁白紙-博客園,通過F12抓包也可以看到 Payload 中請求參數的格式為 Query String Parameters,如下圖:

即打開URL鏈接https://www.baidu.com/s?ie=utf-8&wd=給你一頁白紙-博客園

python代碼發送請求

如果使用python中的 requests.get() 對上圖示例發送get請求,則需使用參數 params,參數值為dict(字典)格式即可,示例如下:

import requests

url = "http://www.baidu.com/s"
params = {"wd": "給你一頁白紙-博客園", "ie": "utf-8"}
res = requests.get(url=url, params=params)
print(res.text)

GET請求中請求主體編碼格式固定,在做接口測試時基本無需確定其編碼格式,較為簡單。

post請求參數格式

對於HTTP協議中的POST請求,其請求參數有不同的編碼格式。

服務端通常是根據請求頭(headers)中的 Content-Type 字段來獲知請求中的消息主體是用何種方式編碼 (即媒體類型),再對請求參數進行對應方式的解析。

post請求常見的編碼方式有四種:

  1. application/x-www-form-urlencoded

  2. multipart/form-data

  3. application/json

  4. text/xml

application/x-www-form-urlencoded

application/x-www-form-urlencoded 是最常見的 POST 提交數據的方式,用於表單數據的提交。瀏覽器的原生form表單,如果不設置enctype屬性,那么最終就會默認以 application/x-www-form-urlencoded 方式提交數據。

說明

POST請求使用 application/x-www-form-urlencoded 對請求參數進行編碼時,有以下特點:

  1. 請求頭header中content-type的值為:application/x-www-form-urlencoded

  2. 請求參數會按照 key1=value1&key2=value2 的方式進行編碼,且 key 和 value 都進行了 URL 轉碼

  3. 服務器收到請求后,會對應的方式對這種編碼格式的請求參數進行解析

  4. 雖然都將請求參數進行了 key1=value1&key2=value2 形式編碼,但GET請求中會將編碼后的內容拼接在URL后。

以請求TesterHome網登陸接口為例:

Request Headers中的 content-type 為 application/x-www-form-urlencoded; charset=UTF-8。

python代碼發送請求

使用python中的 requests.post() 請求上面圖片中的接口時,需使用參數data,參數值為dict(字典)格式即可,代碼如下:

import requests

'''
請求頭的content-type為application/x-www-form-urlencoded
'''

data = {
	"user[login]": "賬號",
	"user[password]": "密碼",
	"user[remember_me]": 0,
	"commit": "登錄"
}
headers = {
	"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36",
    "content-type": "application/x-www-form-urlencoded; charset=UTF-8"
}
url = "https://testerhome.com/account/sign_in"

# 編碼格式為application/x-www-form-urlencoded;charset=UTF-8,使用data參數,參數值為dict,
res = requests.post(url=url, headers=headers, data=data)
print(res.text)

multipart/form-data

multipart/form-data 也是一個常見的 POST 數據提交的方式,用於上傳文件。我們使用表單上傳文件時,必須讓 form 表單的enctype等於 multipart/form-data。

說明

POST 請求使用 multipart/form-data 對請求參數進行編碼時,有以下特點:

  1. 使用 boundary 用於分割不同的字段

  2. 消息主體中按照字段個數又分為多個結構類似的部分,每部分都以--boundary開始,緊接着下一行是內容描述信息,再下一行是字段具體內容(文本或二進制)。如果傳輸的是文件,還要包含文件名和文件類型信息

  3. 消息主體最后以 --boundary-- 標示結束

示例如下:

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundary8G1vtgT1pXWqqHzV

------WebKitFormBoundary8G1vtgT1pXWqqHzV
Content-Disposition: form-data; name="txt"

title
------WebKitFormBoundary8G1vtgT1pXWqqHzV
Content-Disposition: form-data; name="file"; filename="blog.png"
Content-Type: image/png

PNG ... content of blog.png ...
------WebKitFormBoundary8G1vtgT1pXWqqHzV--

python代碼發送請求

例如,我們在請求牛圖網的上傳圖片的接口時,Requests Headers 中為content-type: multipart/form-data; boundary=----WebKitFormBoundary4aA3ZrkOVwUIvmx0,如下圖所示:

在python中使用requests.post()請求該接口,代碼示例如下:

import requests

'''
請求頭的content-type為multipart/form-data
'''

def post_mulitpart_form_data():
    headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36",
        "content-type": "multipart/form-data; boundary=----WebKitFormBoundary4aA3ZrkOVwUIvmx0"
    }
    url = "https://www.niupic.com/api/upload"
    
    filepath = "./dianzan.jpg"
    # 讀取上傳文件的內容
    files = {"file": open(filepath, "rb")}
    # 使用files參數接收請求內容,即讀取的上傳文件內容
    res = requests.post(url=url, headers=headers, files=files).content
    print(json.loads(res))


if __name__ == '__main__':
    post_mulitpart_form_data()

運行結果如下:

C:\Users\xiaoqq\AppData\Local\Programs\Python\Python37\python.exe E:/blog/python接口自動化/flask_demo/test.py
{'status': 'success', 'code': 200, 'data': 'https://i.niupic.com/images/2022/02/20/9V3n.jpg', 'msg': '上傳成功!'}

Process finished with exit code 0

application/x-www-form-urlencoded 與 multipart/form-data 這兩種 POST 請求的數據編碼方式,都是瀏覽器原生支持的,且現階段標准中原生form表單也只支持這兩種方式(通過form元素的enctype屬性指定,默認為 application/x-www-form-urlencoded。其實enctype還支持text/plain,不過用得非常少)。

application/json

在一般公司的普通業務場景中,application/json 很常見,用來告訴服務端,消息主體是序列化后的json字符串,即前端傳給服務端的數據是json格式的。

也就是說,如果請求頭中 content-type 為 application/json,那么我們在使用工具如postman或python腳本模擬請求接口時,請求參數也需要先轉換成json格式,然后才能發送請求。代碼示例如下:

import requests
import json

'''
請求頭的content-type為application/json
'''

headers = {"Content-Type": "application/json;charset=utf8"}
url = "http://127.0.0.1:5000/login"
_data = {
    "username": "lilei",
    "password": "123456"
}

# 這里使用json參數,即json=_data
res = requests.post(url=url, headers=headers, json=_data).text
# 當然還可以使用data參數,但需先將_data轉換為json格式,即data=json.dumps(_data)
# json.dumps()將dict格式轉換成json格式
res = requests.post(url=url, headers=headers, data=json.dumps(_data)).text
print(res)

text/xml

post請求中,有些請求主體的編碼格式為 text/xml,即請求頭中content-type 字段對應值為 text/xml,對於這樣的接口,我們需要使用xml格式的參數去發送請求。

使用 requests.post() 發送請求參數為xml格式的post請求時,只需要將xml文件中的body部分寫成一個字符串類型就行,遇到換行時在后面加個反斜杠,並將這個字符串賦值給data參數。代碼示例如下:

import requests

'''
請求頭的content-type為text/xml
'''

def post_text_xml():
    headers = {"Content-Type": "text/xml"}
    url = "http://httpbin.org/post"

    body = '<?xml version="1.0" encoding = "UTF-8"?>' \
           '<COM>' \
           '<REQ name="給你一頁白紙">' \
           '<USER_ID></USER_ID>' \
           '<COMMODITY_ID>111111</COMMODITY_ID>' \
           '<SESSION_ID>asdfghjklfr0123</SESSION_ID>' \
           '</REQ>' \
           '</COM>'

    res = requests.post(url=url, headers=headers, data=body.encode("utf-8")).text
    print(res)


if __name__ == '__main__':
    post_text_xml()

運行結果如下:

C:\Users\xiaoqq\AppData\Local\Programs\Python\Python37\python.exe E:/blog/python接口自動化/flask_demo/test.py
{
  "args": {}, 
  "data": "<?xml version=\"1.0\" encoding = \"UTF-8\"?><COM><REQ name=\"\u7ed9\u4f60\u4e00\u9875\u767d\u7eb8\"><USER_ID></USER_ID><COMMODITY_ID>111111</COMMODITY_ID><SESSION_ID>asdfghjklfr0123</SESSION_ID></REQ></COM>", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "182", 
    "Content-Type": "text/xml", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.24.0", 
    "X-Amzn-Trace-Id": "Root=1-6211ebd3-2cc90293777649ba01e50b08"
  }, 
  "json": null, 
  "origin": "101.71.37.212", 
  "url": "http://httpbin.org/post"
}


Process finished with exit code 0

總結

這里只介紹了HTTP協議中 GET請求 和 POST請求 常見的請求參數編碼格式,怎樣確定請求參數的編碼格式,以及在python代碼中使用requests發送請求時,需要使用怎樣格式的參數。

我們總結如下:

  1. GET請求,請求參數編碼格式為query string params,requests.get() 發送請求時使用params參數,params的值 (即請求參數) 為字典格式

  2. POST請求主體的編碼格式需要根據請求頭中的content-type字段確定

  3. content-type: application/x-www-form-urlencoded,requests.post() 發送請求時使用data參數,data的值 (即請求參數) 為字典格式

  4. content-type: multipart/form-data,requests.post() 發送請求時使用files參數,files的值 (即請求參數) 即為讀取的上傳文件的內容

  5. content-type: application/json,requests.post() 發送請求時使用json參數,json的值 (即請求參數) 為字典格式,或者也可以使用 data 參數,但此時需要先將請求參數轉換為json格式

  6. content-type: text/xml,requests.post() 發送請求時使用data參數,data的值 (即請求參數) 為 xml 中的body部分內容

具體的腳本編寫方法參考示例代碼。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM