I'm using Python 3.7 with urllib. All work fine but it seems not to athomatically redirect when it gets an http redirect request (307).
This is the error i get:
ERROR 2020-06-15 10:25:06,968 HTTP Error 307: Temporary Redirect
I've to handle it with a try-except and manually send another request to the new Location: it works fine but i don't like it.
These is the piece of code i use to perform the request:
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 is an https resource and i set an header with some Authhorization info and content-type. req.data is a JSON
From urllib documentation i've understood that the redirects are authomatically performed by the the library itself, but it doesn't work for me. It always raises an http 307 error and doesn't follow the redirect URL. I've also tried to use an opener specifiyng the default redirect handler, but with the same result
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)
What could be the problem?
The reason why the redirect isn't done automatically has been correctly identified by yours truly in the discussion in the comments section. Specifically, RFC 2616, Section 10.3.8 states that:
Back to the question - given that
datahas been assigned, this automatically results inget_methodreturningPOST(as per how this method was implemented), and since that the request method isPOST, and the response code is307, anHTTPErroris raised instead as per the above specification. In the context of Python'surllib, this specific section of theurllib.requestmodule raises the exception.For an experiment, try the following code:
Running the code as is may produce the following
Note the subsequent redirect to
getwas done automatically, as the subsequent request was aGETrequest. Commenting outreq.dataassignment line will result in the lack of the "Redirected" output line.Other notable things to note in the exception handling block,
e.read()may be done to retrieve the response body produced by the server as part of theHTTP 307response (sincedatawas posted, there might be a short entity in the response that may be processed?), and thaturljoinis needed as theLocationheader may be a relative URL (or simply has the host missing) to the subsequent resource.Also, as a matter of interest (and for linkage purposes), this specific question has been asked multiple times before and I am rather surprised that they never got any answers, which follows: