遇到问题
在用requests.post方法测试接口调用时,使用data参数得到Response 400
结果;使用json参数得到Response 200
。测试代码如下。
import requests
import json
url = "https://10.20.32.92:8834/scans"
accesskey = 'dc9ada34d59'
secretkey = 'f3b404a433fea25'
header = {
'X-ApiKeys': 'accessKey={accesskey};secretKey={secretkey}'.format(accesskey=accesskey, secretkey=secretkey),
'X-API-Token':'0FADA7F5-8903-4686-81F7-ECD0096628EA',
'Content-type': 'application/json',
'Accept': 'text/plain'
}
data = {
"uuid":"bbd4f805-3966-d464-b2d1-0079e2bcf",
"settings":{
"name":"testscan",
"enabled": "true",
"text_targets": "ip_list",
"agent_group_id": []
}
}
print(requests.post(url, headers=header, data=data, verify=False))
print(requests.post(url, headers=header, json=data, verify=False))
400与200含义
- 400 Bad Request --- The server cannot or will not process the request due to an apparent client error (e.g., malformed request syntax, size too large, invalid request message framing, or deceptive request routing).
- 200 OK --- Standard response for successful HTTP requests. The actual response will depend on the request method used. In a GET request, the response will contain an entity corresponding to the requested resource. In a POST request, the response will contain an entity describing or containing the result of the action.
data与json区别
从requests的官方文档解释中看出:
- data用于发送form-encoded数据,类似HTML表单
- json用于发送not form-encoded数据,例如发送字符串。
- json参数将
Content-Type
改为application/json
- json参数自动对传入的参数调用json.dumps()
从requests源码中的prepare_body函数中可看出针对json参数,修改了
Content-Type
以及调用json.dumps()
的操作。
这样可能不能很好的理解这两个参数的区别,下面使用https://httpbin.org/post
测试,代码如下:
import requests
import json
header = {
'Content-type': 'application/json'
}
data = {
"uuid":"test-uuid",
"settings":{
"name":"test-httpbin",
"enabled": "true",
"text_targets": "ip_list",
}
}
print('\n')
print('-- [ data = data ] -------------------------------------------')
r = requests.post("https://httpbin.org/post", data=data)
print(r.text)
print('\n')
print('-- [ data = json.dumps ] -------------------------------------------')
r = requests.post("https://httpbin.org/post", data=json.dumps(data))
print(r.text)
print('\n')
print('-- [ json = data ] -------------------------------------------')
r = requests.post("https://httpbin.org/post", json=data)
print(r.text)
执行结果如下:
-- [ data = data ] -------------------------------------------
{
"args": {},
"data": "",
"files": {},
"form": {
"settings": [
"name",
"enabled",
"text_targets"
],
"uuid": "test-uuid"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "67",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"url": "https://httpbin.org/post"
}
-- [ data = json.dumps ] -------------------------------------------
{
"args": {},
"data": "{\"uuid\": \"test-uuid\", \"settings\": {\"name\": \"test-httpbin\", \"enabled\": \"true\", \"text_targets\": \"ip_list\"}}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "105",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"json": {
"settings": {
"enabled": "true",
"name": "test-httpbin",
"text_targets": "ip_list"
},
"uuid": "test-uuid"
},
"url": "https://httpbin.org/post"
}
-- [ json = data ] -------------------------------------------
{
"args": {},
"data": "{\"uuid\": \"test-uuid\", \"settings\": {\"name\": \"test-httpbin\", \"enabled\": \"true\", \"text_targets\": \"ip_list\"}}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "105",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"json": {
"settings": {
"enabled": "true",
"name": "test-httpbin",
"text_targets": "ip_list"
},
"uuid": "test-uuid"
},
"url": "https://httpbin.org/post"
}
从结果可看出data=json.dumps()
与json=data
是等价的。而它们与data=data
的差异在于数据存放的字段不同。
- data=data,数据存放在
form
字段中 - json=data,数据存放在
data
和json
字段中
由此可看出,使用requests.post方法中的data或json参数发送数据时,发送的数据被放到不同的键(form或data/json)下。具体从哪个键取数据,这就看接口的实现方式了。因此,若接口从data/json取数据,而调用requests.post方法时使用data参数发送数据,则会导致接口取出的数据为空,从而返回400状态码。
补充1:HTTP状态码分类
HTTP响应状态代码分为五个类别。第一位表示响应的类别,后两位没有分类作用。五个分类如下:
- 1xx informational response – the request was received, continuing process
- 2xx successful – the request was successfully received, understood and accepted
- 3xx redirection – further action needs to be taken in order to complete the request
- 4xx client error – the request contains bad syntax or cannot be fulfilled
- 5xx server error – the server failed to fulfill an apparently valid request
补充2:python字典和Json的区别
从字符串的表示规则上看,Python字典和JSON非常相似。但是Python字典本身是一个完整的数据结构,可实现其自己的所有算法。
- json的key只能是字符串;Python字典的key可以是任何可hash对象
- json的key可以是有序、重复的;Python字典的key不可以重复
- json的key存在默认值undefined;Python字典key默认没有默认值
- json的value只能是字符串、浮点数、布尔值或者null,或者它们构成的数组或者对象
- json访问方式可以是
[]
,也可以是.
,遍历方式分in、of;dict的value仅可以下标访问 - json的字符串强制双引号;Python字典的字符串可以单引号、双引号
- json里只有数组;Python字典可以嵌套tuple
- json:true、false、null;python:True、False、None
- json中文必须是unicode编码,如"\u6211"
- json的类型是字符串;Python字典的类型是字典
网友评论