Python 请求库不工作,而 cURL 工作

Posted

技术标签:

【中文标题】Python 请求库不工作,而 cURL 工作【英文标题】:Python requests library is not working, while cURL is working 【发布时间】:2019-08-13 09:36:21 【问题描述】:

我需要使用 Python 从 Microsoft API 检索 JWT(JSON Web 令牌)(查看 Microsoft Graph 的 this API 文档)

以下使用 requests 库的 Python 代码无法提供 HTTP 响应代码 400,但是,等效的 cURL 命令确实可以返回包含 JWT 的预期 JSON。

Python/requests 代码:

tenant = "<MY_FOO_TENANT>"
token_url = "https://login.microsoftonline.com//oauth2/v2.0/token".format(tenant)
http_headers = 
    'Content-Type':  'application/x-www-form-urlencoded',

http_query_params = 
    "client_id": "<MY_FOO_C_ID>",
    "scope": "<MY_FOO_SCOPE>",
    "client_secret": "<MY_FOO_C_SECRET>",
    "grant_type": "client_credentials",

http_response = requests.post(token_url, params=http_query_params, headers=http_headers)

cURL 命令:

curl -v -X POST \
  --data-urlencode 'client_id=<MY_FOO_C_ID>' \
  --data-urlencode 'scope=<MY_FOO_SCOPE>' \
  --data-urlencode 'client_secret=<MY_FOO_C_SECRET>' \
  --data-urlencode 'grant_type=client_credentials' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  'https://login.microsoftonline.com/<MY_FOO_TENANT>/oauth2/v2.0/token'

requests 库的详细输出中,我可以看到它是对所有这些 HTTP 查询参数进行 URL 编码,所以我倾向于认为这不应该是问题。

Python 实现有什么问题? 如何让它工作?

【问题讨论】:

【参考方案1】:

您应该将http_query_params 传递为data 而不是params。试试下面的代码:

tenant = "<MY_FOO_TENANT>"
token_url = "https://login.microsoftonline.com//oauth2/v2.0/token".format(tenant)
http_headers = 
    'Content-Type':  'application/x-www-form-urlencoded',

http_body = 
    "client_id": "<MY_FOO_C_ID>",
    "scope": "<MY_FOO_SCOPE>",
    "client_secret": "<MY_FOO_C_SECRET>",
    "grant_type": "client_credentials",

http_response = requests.post(token_url, data=http_body, headers=http_headers)

希望对你有帮助

【讨论】:

感谢您的帮助,它的工作原理。然而,这意味着http_query_params 并不是真正的 HTTP 查询参数 (?xxx=yyy&amp;aaa=bbb),而是 HTTP 请求正文,对吧?它在cURL 中起作用的原因是--data-urlencode 实际上并不是对HTTP 查询参数进行编码,而是由于“表单标头格式”(HTTP 标头Content-Type: application/x-www-form-urlencoded)而对HTTP 请求正文进行了URL 编码,对? 嗯,我明白了,基本上你不希望它出现在请求正文中,而是在 URL 中? 我想我被那个“表单标题”和我对 cURL --data-urlencode 的误解所欺骗了。您的建议有效,并且查看requests 文档似乎data= 参数适用于HTTP 正文。所以基本上微软文档中的示例在将这些键/值对呈现为(URL 编码的)HTTP 查询参数时有点误导。 哦,太好了!那么我的代码能解决你的问题吗?或者您现在还面临其他问题吗? 是的,我只想提一下 http_query_params 应该重命名为 http_body 并且(AFAIK)这可能作为 HTTP 正文,因为 HTTP 标头 Content-Type: application/x-www-form-urlencoded

以上是关于Python 请求库不工作,而 cURL 工作的主要内容,如果未能解决你的问题,请参考以下文章

卷曲工作,但 python 请求因 SSLError 而失败

即使 curl 工作,带有代理 407 状态代码的 Python 请求

C# 中的 httpClient 调用超时,而 cUrl 正在工作

Python 请求 API 调用不起作用

Python请求与curl

使用Access和密钥获取请求