[英]python 3.7 urllib.request doesn't follow redirect URL
我正在使用帶有 urllib 的 Python 3.7。 一切正常,但當它收到 http 重定向請求(307)時,它似乎沒有自動重定向。
這是我得到的錯誤:
ERROR 2020-06-15 10:25:06,968 HTTP Error 307: Temporary Redirect
我必須使用 try-except 來處理它並手動向新位置發送另一個請求:它工作正常,但我不喜歡它。
這些是我用來執行請求的代碼:
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 資源,我設置了一個帶有一些授權信息和內容類型的 header。 req.data 是 JSON
從 urllib 文檔中,我了解到重定向是由庫本身自動執行的,但它對我不起作用。 它總是引發 http 307 錯誤並且不遵循重定向 URL。 我還嘗試使用指定默認重定向處理程序的開啟程序,但結果相同
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)
可能是什么問題呢?
您在評論部分的討論中真正正確地確定了重定向未自動完成的原因。 具體來說, RFC 2616 第 10.3.8 節指出:
如果收到 307 狀態代碼以響應 GET 或 HEAD 以外的請求,除非用戶可以確認,否則用戶代理不得自動重定向請求,因為這可能會改變發出請求的條件。
回到問題 - 鑒於data
已被分配,這會自動導致get_method
返回POST
(根據此方法的實現方式),並且由於請求方法是POST
,響應代碼是307
,而是引發HTTPError
按照上述規范。 在 Python 的urllib
上下文中, urllib.request
模塊的這個特定部分會引發異常。
對於實驗,請嘗試以下代碼:
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
按原樣運行代碼可能會產生以下結果
Redirected -> http://httpbin.org/redirect/1
Response URL -> http://httpbin.org/get
請注意,后續重定向到get
是自動完成的,因為后續請求是GET
請求。 注釋掉req.data
分配行將導致缺少“重定向” output 行。
在異常處理塊中需要注意的其他值得注意的事情,可以e.read()
來檢索服務器生成的響應主體,作為HTTP 307
響應的一部分(由於發布了data
,響應中可能有一個短實體可能會被處理?),並且需要urljoin
,因為Location
header 可能是后續資源的相對 URL(或只是缺少主機)。
此外,作為一個感興趣的問題(並且出於鏈接目的),這個特定問題之前已被多次詢問,我很驚訝他們從未得到任何答案,如下所示:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.