Dizzy
Dizzy

Reputation: 3

Stop urllib following HTTP redirects in python3

I want to prevent urllib to stop follow redirects. Based on an old post, ref : Is there an easy way to request a URL in python and NOT follow redirects?

I found the following code snippet that works, but this is in python2

class NoRedirectHandler(urllib2.HTTPRedirectHandler):
    def http_error_302(self, req, fp, code, msg, headers):
        infourl = urllib.addinfourl(fp, headers, req.get_full_url())
        infourl.status = code
        infourl.code = code
        return infourl
    http_error_300 = http_error_302
    http_error_301 = http_error_302
    http_error_303 = http_error_302
    http_error_307 = http_error_302

opener = urllib2.build_opener(NoRedirectHandler())
urllib2.install_opener(opener)

I tried to convert this code to python3 and got the following error.

class NoRedirectHandler(urllib.request.HTTPRedirectHandler):
    # alternative handler
    def http_error_300(self, req, fp, code, msg, header_list):
        data = urllib.request.addinfourl(fp, header_list, req.get_full_url())
        data.status = code
        data.code = code
        return data

    # setup aliases
    http_error_301 = http_error_300
    http_error_302 = http_error_300
    http_error_303 = http_error_300
    http_error_307 = http_error_300


urllib.request.install_opener(urllib.request.build_opener(NoRedirectHandler()))
Traceback (most recent call last):
  File "/home/script.py", in <module>
    res = urllib.request.urlopen(req, timeout=40)
  File "/usr/lib/python3.10/urllib/request.py", line 216, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.10/urllib/request.py", line 525, in open
    response = meth(req, response)
  File "/usr/lib/python3.10/urllib/request.py", line 634, in http_response
    response = self.parent.error(
  File "/usr/lib/python3.10/urllib/request.py", line 557, in error
    result = self._call_chain(*args)
  File "/usr/lib/python3.10/urllib/request.py", line 496, in _call_chain
    result = func(*args)
  File "/home/script.py",i n http_error_300
    data.status = code
AttributeError: can't set attribute 'status'

How do I make this work in python3?

Upvotes: 0

Views: 113

Answers (1)

Nikhil
Nikhil

Reputation: 1

The error you are encountering in Python 3, specifically the AttributeError: can't set attribute 'status', is caused by a difference in the addinfourl object between Python 2 and Python 3. In Python 3, the status and code attributes of the addinfourl object are read-only properties.

In the original Python 2 code, it was possible to directly assign values to the status and code attributes of addinfourl objects. However, in Python 3, the addinfourl class in the urllib module defines the status and code attributes as read-only properties. This means that attempting to assign a value to these attributes will result in an AttributeError.

from urllib.request import HTTPRedirectHandler, build_opener, install_opener, addinfourl

from urllib.error import HTTPError

class NoRedirectResponse(addinfourl):
    def __init__(self, fp, headers, url, code):
        addinfourl.__init__(self, fp, headers, url)
        self.code = code
        self.status = code

class NoRedirectHandler(HTTPRedirectHandler):
    def http_error_300(self, req, fp, code, msg, headers):
        return NoRedirectResponse(fp, headers, req.get_full_url(), code)
    http_error_301 = http_error_300
    http_error_302 = http_error_300
    http_error_303 = http_error_300
    http_error_307 = http_error_300

install_opener(build_opener(NoRedirectHandler()))

Upvotes: -1

Related Questions