Python Glossary English

все Python 3urllib.requestпонятие

urllib.request.HTTPRedirectHandler

ошибки и перенаправления

Обработчик перенаправлений: сам переходит по Location для ответов 301/302/303/307/308 и ловит циклы.

Синтаксис

urllib.request.HTTPRedirectHandler()

Ловушка: при 301/302/303 POST превращается в GET и тело теряется — новый адрес получает пустой запрос, а POST с ответом 307/308 не повторяется вовсе и даёт HTTPError. Переходов не больше 10 (max_redirections). Чтобы перенаправления не выполнялись, наследуются от класса и возвращают None из redirect_request(): тогда 3xx приходит как HTTPError с заголовком Location.

Примеры

import email.message, io, urllib.error, urllib.request, urllib.response
def reply(req, code, body=b'', **headers):
    msg = email.message.Message()
    for name, value in headers.items():
        msg[name.replace('_', '-')] = value
    resp = urllib.response.addinfourl(io.BytesIO(body), msg, req.full_url, code)
    resp.msg = 'demo'
    return resp
class Server(urllib.request.BaseHandler):
    handler_order = 100
    def http_open(self, req):
        print(req.get_method(), req.selector, req.data)
        if req.selector == '/old':
            return reply(req, 302, Location='/new')
        return reply(req, 200, b'ok')
opener = urllib.request.build_opener(Server)
opener.open(urllib.request.Request('http://example.com/old', data=b'x=1'))
# → POST /old b'x=1' / GET /new None
import email.message, io, urllib.error, urllib.request, urllib.response
def reply(req, code, body=b'', **headers):
    msg = email.message.Message()
    for name, value in headers.items():
        msg[name.replace('_', '-')] = value
    resp = urllib.response.addinfourl(io.BytesIO(body), msg, req.full_url, code)
    resp.msg = 'demo'
    return resp
class Server(urllib.request.BaseHandler):
    handler_order = 100
    def http_open(self, req):
        return reply(req, 302, Location='/new')
class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None
try:
    urllib.request.build_opener(Server, NoRedirect).open('http://example.com/old')
except urllib.error.HTTPError as e:
    print(e.code, e.headers['Location'])  # → 302 /new

См. также

Открыть в полном глоссарииdocs.python.orgСообщить о неточности