簡體   English   中英

python 3.7 urllib.request 不遵循重定向 URL

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM