请求和HTTP 302状态代码

I wanted briefly to touch on the behaviour of the Python Requests library when it receives an HTTP 302 message. This has come up a couple of times on GitHub, and has usually been considered a bug, so it’s worth briefly stepping in and explaining what Requests does and why it does it.

我想简要介绍一下Python Requests库在收到HTTP 302消息时的行为。 这个问题在GitHub上已经出现过两次,通常被认为是一个错误,因此有必要简要介绍一下并解释Requests的作用以及为什么这么做。

First, HTTP 302 is defined in RFC 2616. You can find the full definition there, but I’ll reproduce some of it here, with the relevant passage highlighted (emphasis mine):

首先,在RFC 2616中定义了HTTP 302。 您可以在此处找到完整的定义,但是我将在此处重现其中的一些定义,并突出显示相关段落(强调我的意思):

302 Found

找到302个

The requested resource resides temporarily under a different URI. Since the redirection might be altered on occasion, the client SHOULD continue to use the Request-URI for future requests.

所请求的资源临时位于其他URI下。 由于重定向有时可能会更改,因此客户端应继续将Request-URI用于将来的请求。

The temporary URI SHOULD be given by the Location field in the response.

临时URI应该由响应中的Location字段给出。

If the 302 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

如果响应GET或HEAD以外的请求而收到302状态码,则用户代理不得自动重定向该请求,除非用户可以确认 ,因为这可能会更改发出该请求的条件。

OK, fine. The RFC is very clear on this point, right? It would be failing to comply with the RFC if Requests did not prompt for user input before redirecting after a 302.

好的。 RFC在这一点上非常清楚,对吗? 如果在302之后重定向之前,请求没有提示用户输入,则将不符合RFC。

Actually, it’s not that simple. The reason is that almost all browsers do NOT implement this behaviour and never have. Instead, they treat the 302 as an HTTP 303 See Other response: that is, they automatically and without prompting issue a GET on the redirected-to URI.

其实不是那么简单。 原因是几乎所有浏览器都不会实现这种行为,而且永远不会实现。 取而代之的是,他们将302视为HTTP303。请参阅“其他响应”:也就是说,他们自动且不提示对重定向到的URI发出GET。

This behaviour is so prevalent that RFC 2616 contains a note (emphasis mine):

此行为非常普遍,以致RFC 2616包含注释(强调我的意思):

Note: RFC 1945 and 2068 specify that the client is not allowed to change the method on the redirected request. However, most existing user agent implementations treat 302 as if it were a 303 response, performing a GET on the Location field-value regardless of the original request method. The status codes 303 and 307 have been added for servers that wish to make unambiguously clear which kind of reaction is expected by the client.

注意:RFC 1945和2068指定不允许客户端更改重定向请求的方法。 但是,大多数现有的用户代理实现都将302视为303响应,而不管原始请求方法如何,都对Location字段值执行GET。 已为希望明确阐明客户端期望哪种React的服务器添加了状态代码303和307。

Hmm.

该怎么办? (What To Do?)

So then, what should Requests do? We can’t actually require the user stop and say OK, so we would need to obtain permission beforehand. We do this by taking the allow_redirects parameter on all the Request verbs. This parameter defaults to True.

那么,请求应该怎么做? 我们实际上不能要求用户停下来并说OK,因此我们需要事先获得许可。 为此,我们对所有Request动词采用allow_redirects参数。 此参数默认为True

The way I see it, Requests has three options:

我的看法是,请求有三个选择:

  1. Follow the specification, and only redirect if allow_redirects is True. Additionally, use the same verb on the Location field.
  2. Do what browsers do. Only redirect is allow_redirects is True. Issue a GET request on the Location field.
  3. One of the above, but ensure that we got permission by using some different field, or ternary logic in allow_redirects. (False, True, and Yes-I-Really-Mean-It?)
  1. 遵循规范,仅在allow_redirectsTrue重定向。 此外,在“位置”字段上使用相同的动词。
  2. 做浏览器做什么。 仅重定向是allow_redirectsTrue 。 在“位置”字段上发出GET请求。
  3. 以上之一,但请确保通过使用allow_redirects一些不同字段或三元逻辑来获得许可。 (错误,正确和是,我真的是真的吗?)

There is no right answer here. If we do 1, we get the warm fuzzy feeling that says ‘I am doing What The Spec Says’, while in the background everything fails because web servers expect browsers and not Requests. If we do 3, we have some horribly complicated API to ensure that we ask permission, even though we sort-of asked permission anyway in the allow_redirects field.

这里没有正确的答案。 如果执行1,我们会得到温暖的模糊感觉,说“我正在按照规格说”,而在后台一切都失败了,因为Web服务器需要浏览器而不是Requests。 如果执行3,则即使在allow_redirects字段中仍然对请求的权限进行了排序,我们也将使用一些非常复杂的API来确保请求权限。

Doing 2 is more subtle. For 99% of people, Requests works properly. Web servers that genuinely care about what we do shouldn’t be issuing 302s because they must assume that they might get hit by a web browser, which will do The Wrong Thing (TM). However, 1 person in 100 believes the RFCs to be sacred, and will file bugs against Requests, insisting that we are doing The Wrong Thing (TM) and that the world will collapse and that we’ll go to hell and that Batman will come and get us.

做2更加微妙。 对于99%的人,请求正常运行。 真正关心我们的操作的Web服务器不应发布302,因为它们必须假定它们可能会受到Web浏览器的攻击,而Web浏览器将执行The Wrong Thing(TM)。 但是,每100个人中就有1个人认为RFC是神圣的,并且会针对请求提出错误,坚持认为我们正在做错事(TM),世界将崩溃,我们将下地狱,蝙蝠侠会来并得到我们。

Ignore those guys.

忽略那些家伙。

底线 (The Bottom Line)

Here’s the reality. Ignore Postel’s Law, ignore the RFC-fascists and ignore the doubters. Instead, follow the following law:

这就是现实。 忽略Postel法则 ,忽略RFC法西斯主义者和怀疑者。 相反,请遵循以下法律:

It doesn’t matter if you comply with the spec, if you don’t work out of the box with the majority of implementations you are wrong.

您是否遵守规范并不重要,如果您在大多数实现都没有开箱即用,那您就错了

要求 (For Requests)

翻译自: https://www.pybloggers.com/2013/02/requests-and-the-http-302-status-code/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值