4

我正在使用 urllib2 使用 Python 2.7.3 执行 http 发布请求。我的请求返回 HTTPError 异常(HTTP 错误 502:代理错误)。

查看与 Charles 的消息流量,我看到正在发生以下情况:

  1. 我使用 urllib2 发送 HTTP 请求(POST /index.asp?action=login HTTP/1.1)
  2. 远程服务器回复状态 303 和 ../index.asp?action=news 的位置标头
  3. urllib2 重试发送 get 请求:(GET /../index.asp?action=news HTTP/1.1)
  4. 远程服务器回复状态为 502(代理错误)

502 回复在响应正文中包含以下内容:“DNS 查找失败:10.0.0.30:80index.asp”(注意格式错误的 URL)

所以我认为这意味着远程服务器网络上的代理服务器在请求中看到“/../index.asp” URL 并误解它,从而使用错误的 URL 发送我的请求。

当我使用浏览器 (Chrome) 发出相同的请求时,重试将发送到 GET /index.asp?action=news。因此,Chrome 从 URL 中去掉了前导的“/..”,远程服务器回复了一个有效的响应。

这是一个 urllib2 错误吗?有什么办法可以让重试忽略 URL 中的“/..”吗?或者有没有其他方法可以解决这个问题?认为这可能是一个 urllib2 错误,我用请求替换了 urllib2,但请求产生了相同的结果。当然,这可能是因为 requests 是建立在 urllib2 之上的。

谢谢你的帮助。

4

1 回答 1

2

与该 302 一起发送的位置在多个方面都是错误的。

首先,如果您阅读RFC2616(HTTP/1.1 标头字段定义)14.30 Location,则 Location 必须是绝对URI,而不是相对URI。10.3.3 节明确说明这是相关定义。

其次,即使允许使用相对 URI,RFC 1808.. ,Relative Uniform Resource Locators,4. Resolving Relative URLs,第 6 步,仅在模式中指定特殊处理<segment>/../。这意味着相对 URL 不应以... 因此,即使基本 URL 是http://example.com/foo/bar/并且相对 URL 是../baz/,解析的 URL 也不是http://example.com/foo/baz/,而是http://example.com/foo/bar/../baz。(当然大多数服务器会以同样的方式处理这些,但这取决于每个服务器。)

最后,即使您在解析之前确实结合了相对 URL 和基本 URL ..,路径以 开头的绝对 URI..也是无效的。

因此,该错误存在于服务器的配置中。

现在,碰巧许多用户代理都会解决这个错误。特别是,他们变成/../foo阻止/foo用户(或在他们不知情的情况下代表他们运行的任意 JS)尝试进行“逃避 webroot”攻击。

但这并不意味着urllib2应该这样做,或者不这样做是错误的。当然urllib2应该更早地检测到错误,以便它可以告诉您“无效路径”或其他内容,而不是一起运行一个非法的绝对 URI,这会混淆服务器向您发送无意义的错误。但失败对的。

说服务器配置错误固然很好,但除非您是服务器的负责人,否则您可能会面临一场艰苦的战斗,试图让他们相信他们的网站已损坏并且需要修复它适用于他们关心的每个网络浏览器。这意味着您可能需要编写自己的解决方法来处理他们的网站。

做到这一点的方法urllib2是为您自己HTTPRedirectHandler提供一个方法实现,redirect_request该方法可以识别这种情况并返回Request与默认代码不同的值(特别是,http://example.com/index.asp?action=news而不是http://example.com/../index.asp?action=news)。

于 2012-11-14T01:30:54.777 回答