【问题标题】:How to make Python Requests follow a POST redirect?如何使 Python 请求遵循 POST 重定向?
【发布时间】:2020-04-17 13:48:45
【问题描述】:

使用以下代码,服务器以 301 重定向响应,但客户端将 POST 更改为 GET,这是无用的行为,因为 GET 端点不存在。使用 CURL -L -X POST 可以正常工作。使用 python2 和 python3 以及在多个版本的 Raspbian 上,此行为是相同的。

>>> import requests
>>> url = "https://registry.micronets.in/mud/v1/register- 
device/DAWG/AgoNDQcDDgg/aabbccddeeffgg"
>>> response = requests.post(url)
>>> response
<Response [404]>

# Server Log: (Note - both endpoints, are on the same server using virtual hosts)
redirecting to: https://hotdawg.micronets.in/registry/devices/register- device/AgoNDQcDDgg/aabbccddeeffgg
POST /registry/v1/register-device/DAWG/AgoNDQcDDgg/aabbccddeeffgg 301 16.563 ms - 122
{
  "status": 404
}
GET /vendors//register-device/AgoNDQcDDgg/aabbccddeeffgg 404 0.604 ms - 14

# CURL version (succeeds)
curl -L -X POST "https://registry.micronets.in/mud/v1/register- 
device/DAWG/AgoNDQcDDgg/aabbccddeeffgg"
Device registered (insert): {
  "model": "AgoNDQcDDgg",
  "pubkey": "aabbccddeeffgg",
  "timestamp": "2019-12-27 15:44:14 UTC",
  "_id": "HBlQzXfBnoB3N4fN"
}

# Server Log: (from CURL)
redirecting to: https://hotdawg.micronets.in/registry/devices/register- 
device/AgoNDQcDDgg/aabbccddeeffgg
POST /registry/v1/register-device/DAWG/AgoNDQcDDgg/aabbccddeeffgg 301 0.364 ms - 122
POST /vendors//register-device/AgoNDQcDDgg/aabbccddeeffgg 200 1.745 ms - 157

【问题讨论】:

  • 您是否尝试过在您的POST 请求中将allow_redirects 标志用于True
  • (我怀疑问题是重定向到另一个域(实际上是一个子域)。我推测如果重定向到同一域上的不同端点,POST 重定向会成功)。如前所述,两个端点都在同一个物理服务器上,使用 nginx 中的虚拟主机进行映射。所以两个端点的IP地址是一样的
  • aws_appentice 我会尝试,但我读到这是除了 HEAD 请求之外的默认行为。是的,刚试过,同样的行为
  • @αԋɱҽԃαмєяιcαη 如果服务器配置不正确,那么为什么curl -L -X POST 可以正常工作?
  • @αԋɱҽԃαмєяιcαη 来自服务器的 301 重定向仅指定 URL,而不是方法。该方法由客户端在重定向时选择

标签: python redirect post python-requests


【解决方案1】:

检查您的nginx 配置:Reference

  1. 您已经发送了一个POST 请求,该请求已经成功到达服务器。
  2. 现在服务器正在处理POST 请求并根据您分配的规则进行处理。
  3. 出现问题是因为您的配置上的重定向分配是通过 GET 请求调用结束 url
  4. 你责备requests 它没有处理重定向,但它已经正确处理了它。但是您将其与curl 与它一起使用-L 进行比较,默认情况下强制服务器推送请求。 (等等,curl --list-only -X POST "https://registry.micronets.in/mud/v1/register-device/DAWG/AgoNDQcDDgg/aabbccddeeffgg")你在哪里使用-X,它是在HTTPS url 上的HTTP

-X, --request will be used for all requests, which if you for example use -L, --location may cause unintended side-effects when curl doesn't change request method according to the HTTP 30x response codes - and similar. curl doesn't change request method 在您的情况下为POST 的部分,并且已经强制服务器使用它。但对于requests,情况完全不同。

import requests

with requests.Session() as ses:
    r = ses.post(
        "https://registry.micronets.in/mud/v1/register-device/DAWG/AgoNDQcDDgg/aabbccddeeffgg", allow_redirects=True)
    print(r.history[0].headers['Location'])

输出:

https://hotdawg.micronets.in/registry/devices/register-device/AgoNDQcDDgg/aabbccddeeffgg

最后,我确实相信这个位于 linode 服务器后面的 nginx 服务器,这是一个常见问题。

知识在这里:

import requests

with requests.Session() as ses:
    r = ses.post(
        "https://registry.micronets.in/mud/v1/register-device/DAWG/AgoNDQcDDgg/aabbccddeeffgg", allow_redirects=True)
    print(r.history, r.history[0].reason)
    print(r.status_code, r.reason)

输出:

[<Response [301]>] Moved Permanently
404 Not Found

但是POST 给它!

r = requests.post(
    "https://hotdawg.micronets.in/registry/devices/register-device/AgoNDQcDDgg/aabbccddeeffgg")
print(r)

输出:

<Response [200]>

确认您发送了POST 请求并且它已完全切换到GET

话虽如此,正如我在上面解释的那样,curl -X 被设置为强制服务器使用 POST 直到结束点所使用的方法。

【讨论】:

  • 这仍然返回 404 并且不回答 OP 的问题
【解决方案2】:

我宁愿接受一个更好的答案,否则我计划按如下方式解决该问题:

response = requests.post(url, allow_redirects=False)
if response.status_code == 301:
    response = requests.post(response.headers['Location'])

response = requests.post(url, allow_redirects=False)
i=10
while i > 0 and response.status_code == 301:
    response = requests.post(response.headers['Location'], allow_redirects=False)
    i -= 1

【讨论】:

  • 这里有什么新东西?调用标题位置。就这些吗?
  • @αԋɱҽԃαмєяιcαη 这里的新功能是它解决了我的问题。也说明我的nginx配置没有问题
猜你喜欢
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 2013-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-09
  • 1970-01-01
相关资源
最近更新 更多