首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python3.7 urllib.request不遵循重定向URL

Python3.7 urllib.request不遵循重定向URL
EN

Stack Overflow用户
提问于 2020-06-15 08:11:12
回答 1查看 4.2K关注 0票数 2

我在与urllib一起使用Python3.7。所有的工作都很好,但是当它得到一个http重定向请求(307)时,它似乎不会以其他方式重定向。

这是我得到的错误:

代码语言:javascript
运行
复制
ERROR 2020-06-15 10:25:06,968 HTTP Error 307: Temporary Redirect

我不得不尝试-除了手动发送另一个请求到新的位置:它工作良好,但我不喜欢它。

下面是我用来执行请求的代码:

代码语言:javascript
运行
复制
      req = urllib.request.Request(url)
      req.add_header('Authorization', auth)
      req.add_header('Content-Type','application/json; charset=utf-8')
      req.data=jdati  
      self.logger.debug(req.headers)
      self.logger.info(req.data)
      resp = urllib.request.urlopen(req)

url是https资源,我用一些Authhorization和内容类型设置了一个标题。req.data是一个JSON

从urllib文档中,我了解重定向是由库本身真实地执行的,但它对我不起作用。它总是引发一个http 307错误,并且不遵循重定向URL。我还尝试使用(默认重定向处理程序),但结果相同

代码语言:javascript
运行
复制
  opener = urllib.request.build_opener(urllib.request.HTTPRedirectHandler)          
  req = urllib.request.Request(url)
  req.add_header('Authorization', auth)
  req.add_header('Content-Type','application/json; charset=utf-8')
  req.data=jdati  
  resp = opener.open(req)         

有什么问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-15 09:25:25

重定向没有自动完成的原因已经在注释部分的讨论中被您正确地识别了。具体而言,RFC 2616,10.3.8节指出:

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

回到问题--考虑到已经分配了data,这将自动导致get_method返回POST (按照该方法是如何实现的),并且由于请求方法是POST,响应代码是307,因此将按照上述规范引发HTTPError。在Python的urllib上下文中,urllib.request模块的这一特定部分引发异常。

对于实验,请尝试以下代码:

代码语言:javascript
运行
复制
import urllib.request
import urllib.parse


url = 'http://httpbin.org/status/307'
req = urllib.request.Request(url)
req.data = b'hello'  # comment out to not trigger manual redirect handling
try:
    resp = urllib.request.urlopen(req)
except urllib.error.HTTPError as e:
    if e.status != 307:
        raise  # not a status code that can be handled here
    redirected_url = urllib.parse.urljoin(url, e.headers['Location'])
    resp = urllib.request.urlopen(redirected_url)
    print('Redirected -> %s' % redirected_url)  # the original redirected url 
print('Response URL -> %s ' % resp.url)  # the final url

按原样运行代码可能会产生以下结果

代码语言:javascript
运行
复制
Redirected -> http://httpbin.org/redirect/1
Response URL -> http://httpbin.org/get 

注意,对get的后续重定向是自动完成的,因为随后的请求是GET请求。注释掉req.data赋值行将导致缺少“重定向”输出行。

在异常处理块中要注意的其他值得注意的事情是,可以执行e.read()来检索服务器作为HTTP 307响应的一部分而产生的响应体(由于发布了data,响应中可能有一个短的实体可被处理?),并且需要urljoin,因为Location头可能是与后续资源的相对URL (或主机丢失)。

此外,作为一个令人感兴趣的问题(为了联系的目的),这一具体问题以前曾多次被问过,我感到相当惊讶的是,他们从未得到任何答案,如下所示:

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62384020

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档