英文:
What do I need to change so my tornado code can post successfully?
问题
以下是要翻译的内容,只包括代码部分的翻译:
import requests
from pprint import pprint
import json
PEM = '/full/path/to/my.pem'
client_id='cliendID'
client_secret='clientSecret'
USER='myuser'
PSWD='mypwd'
url = 'https://theurl.com/request/'
data = {
"grant_type": "password",
"username": USER,
"password": PSWD
}
auth = (client_id, client_secret)
response = requests.post(url, auth=auth, data=data, verify=PEM)
answer = response.json()['answer']
print(answer)
curl -iv --user cliendID:clientSecret --key /full/path/to/server.key --cert /full/path/to/my.pem -F grant_type=password -F username=myuser -F password=mypwd https://theurl.com/request/
from tornado.httpclient import AsyncHTTPClient
from tornado.ioloop import IOLoop
import json
async def get_content():
PEM = '/full/path/to/my.pem'
client_id='cliendID'
client_secret='clientSecret'
url = 'https://theurl.com/request/'
USER='myuser'
PSWD='mypwd'
data = {
"grant_type": "password",
"username": USER,
"password": PSWD
}
bodyData = json.dumps(data)
http_client = AsyncHTTPClient()
response = await http_client.fetch(url,
method='POST',
body=bodyData,
auth_username=client_id,
auth_password=client_secret,
ca_certs=PEM)
print(response.body.decode())
async def main():
await get_content()
if __name__ == "__main__":
io_loop = IOLoop.current()
io_loop.run_sync(main)
请注意,这只是提供的代码的翻译部分,不包括其他内容。如果您有其他问题或需要更多帮助,请随时告诉我。
英文:
I have the following (with some strings modified) which works when using the requests
library.
import requests
from pprint import pprint
import json
PEM = '/full/path/to/my.pem'
client_id='cliendID'
client_secret='clientSecret'
USER='myuser'
PSWD='mypwd'
url = 'https://theurl.com/request/'
data = {
"grant_type": "password",
"username": USER,
"password": PSWD
}
auth = (client_id, client_secret)
response = requests.post( url, auth=auth, data=data, verify=PEM )
answer = response.json()['answer']
print( answer )
The answer printed is what I expect.
The following usage of curl
also works:
curl -iv --user cliendID:clientSecret --key /full/path/to/server.key --cert /full/path/to/my.pem -F grant_type=password -F username=myuser -F password=mypwd https://theurl.com/request/
However, when I try to do the same using Tornado and AsyncHTTPClient, I get a "Bad Request" response. Some sample Tornado code is:
from tornado.httpclient import AsyncHTTPClient
from tornado.ioloop import IOLoop
import json
async def get_content():
PEM = '/full/path/to/my.pem'
client_id='cliendID'
client_secret='clientSecret'
url = 'https://theurl.com/request/'
USER='myuser'
PSWD='mypwd'
data = {
"grant_type": "password",
"username": USER,
"password": PSWD
}
bodyData = json.dumps( data )
http_client = AsyncHTTPClient()
response = await http_client.fetch( url,
method = 'POST',
body = bodyData,
auth_username = client_id,
auth_password = client_secret,
ca_certs = PEM )
print( response.body.decode() )
async def main():
await get_content()
if __name__ == "__main__":
io_loop = IOLoop.current()
io_loop.run_sync(main)
If I had to guess, I believe the issue is with how I am sending the bodyData.
What do I need to change in the Tornado code so this will work...?
答案1
得分: 2
默认情况下,requests
库和Tornado的AsyncHTTPClient
都将请求体数据发送为表单编码数据(即使用Content-Type: application/x-www-form-urlencoded
)。
requests
库会自动使用正确的内容类型对数据字典进行编码。
但是,使用Tornado的客户端,您需要手动对数据进行如下编码:
from urllib.parse import urlencode
bodyData = urlencode(data)
...
错误的原因:
您收到"Bad Request"错误是因为您将数据发送为JSON,但Content-Type标头(由Tornado自动发送)仍然为www-form-urlencoded
。这意味着服务器无法解码您提供的数据,因为它不知道数据是JSON格式的。
英文:
By default, the requests
library and Tornado's AsyncHTTPClient
, both, send the body data as form encoded data (i.e. with Content-Type: application/x-www-form-urlencoded
).
The requests
library automatically encodes the data dict with the correct content type.
But with Tornado's client, you're requried to manually encode the data as follows:
from urllib.parse import urlencode
bodyData = urlencode(data)
...
Cause of the error:
You're getting the Bad Request error because you're sending the data as JSON but the Content-Type header (sent automatically by Tornado) still says www-form-urlencoded
. That means the server can't decode your supplied data because it doesn't know that it's JSON.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论