我正在尝试在 Python 中使用 urllib3 将 x-www-form-urlencoded 数据发布到 ServiceNow API。通常的curl命令看起来像这样
curl -d "grant_type=password&client_id=<client_ID>&client_secret=<client_Secret>&username=<username>&password=<password>" https://host.service-now.com/oauth_token.do
到目前为止,我已经尝试过以下方法:
import urllib3
import urllib.parse
http = urllib3.PoolManager()
data = {"grant_type": "password", "client_id": "<client_ID>", "client_secret": "<client_Secret>", "username": "<username>", "password": "<password>"}
data = urllib.parse.urlencode(data)
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
accesTokenCreate = http.request('POST', "https://host.service-now.com/outh_token.do", headers = headers, fields= data)
print(accesTokenCreate.data)
但是,它不会生成类似于curl命令的结果,并给出如下错误:
Traceback (most recent call last):
File "/VisualStudio/Python/ServiceNow.py", line 18, in <module>
accesTokenCreate = http.request('POST', "https://visierdev.service-now.com/outh_token.do", headers = headers, fields= data)
File "/usr/local/homebrew/lib/python3.7/site-packages/urllib3/request.py", line 80, in request
method, url, fields=fields, headers=headers, **urlopen_kw
File "/usr/local/homebrew/lib/python3.7/site-packages/urllib3/request.py", line 157, in request_encode_body
fields, boundary=multipart_boundary
File "/usr/local/homebrew/lib/python3.7/site-packages/urllib3/filepost.py", line 78, in encode_multipart_formdata
for field in iter_field_objects(fields):
File "/usr/local/homebrew/lib/python3.7/site-packages/urllib3/filepost.py", line 42, in iter_field_objects
yield RequestField.from_tuples(*field)
TypeError: from_tuples() missing 1 required positional argument: 'value'
有人可以帮助我了解如何正确使用 urllib3 将此类数据发布到 ServiceNow API 吗?
根据urlllib3文档,您没有正确使用
request()
方法。具体来说,代码中的 fields
参数不是“键/值字符串和键/文件元组的参数”。它不应该是 URL 编码的字符串。
要修复您的代码,只需将
request
调用的 fields
参数更改为 body
,如下所示:
accesTokenCreate = http.request(
'POST', "https://host.service-now.com/outh_token.do",
headers=headers, body=data)
更好的是,您可以使用
request_encode_body()
函数并直接传入字段,而无需 urlencode
-ing 它,并让该函数为您调用 urllib.parse.urlencode()
(根据相同的文档)。
使用 urllib3 发送 POST application/x-www-form-urlencoded 请求的更短方法是使用
request_encode_body
方法和 encode_multipart=False
,如here所述:
import json
import urllib3
http = urllib3.PoolManager()
r = http.request_encode_body(
'POST', 'http://httpbin.org/post', encode_multipart=False, fields={'hello': 'world'}
)
json_data = json.loads(r.data)
print(json_data['form']) # {'hello': 'world'}
print(json_data['headers']) # {'Content-Type': 'application/x-www-form-urlencoded'}