Commit 828023b6 authored by Jeremy Hylton's avatar Jeremy Hylton

Repair redirect handling and raise URLError on host-not-found.

The latest changes to the redirect handler couldn't possibly have been
tested, because they did not compute a newurl and failed with a
NameError.  The __name__ == "__main__": block has a test for
redirects.

Also, fix SF bug 723831.  A urlopen() that failed because the host was
not found raised a socket.gaierror unlike earlier versions of
urllib2.  The problem is that httplib actually establishes the
connection at a different point starting with Python 2.2.  Move the
try/except to endheaders(), which is where the connection gets
established.
parent 258dfebf
...@@ -416,14 +416,25 @@ class HTTPRedirectHandler(BaseHandler): ...@@ -416,14 +416,25 @@ class HTTPRedirectHandler(BaseHandler):
Request to allow http_error_30x to perform the redirect. Otherwise, Request to allow http_error_30x to perform the redirect. Otherwise,
raise HTTPError if no-one else should try to handle this url. Return raise HTTPError if no-one else should try to handle this url. Return
None if you can't but another Handler might. None if you can't but another Handler might.
""" """
if (code in (301, 302, 303, 307) and req.method() in ("GET", "HEAD") or # XXX 301 and 302 errors must have a location or uri header.
code in (302, 303) and req.method() == "POST"): # Not sure about the other error codes.
# Strictly (according to RFC 2616), 302 in response to a POST if "location" in headers:
# MUST NOT cause a redirection without confirmation from the user newurl = headers["location"]
# (of urllib2, in this case). In practice, essentially all clients elif "uri" in headers:
# do redirect in this case, so we do the same. newurl = headers["uri"]
else:
return
newurl = urlparse.urljoin(req.get_full_url(), newurl)
m = req.get_method()
if (code in (301, 302, 303, 307) and m in ("GET", "HEAD")
or code in (302, 303) and m == "POST"):
# Strictly (according to RFC 2616), 302 in response to a
# POST MUST NOT cause a redirection without confirmation
# from the user (of urllib2, in this case). In practice,
# essentially all clients do redirect in this case, so we
# do the same.
return Request(newurl, headers=req.headers) return Request(newurl, headers=req.headers)
else: else:
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp) raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
...@@ -777,25 +788,25 @@ def encode_digest(digest): ...@@ -777,25 +788,25 @@ def encode_digest(digest):
class AbstractHTTPHandler(BaseHandler): class AbstractHTTPHandler(BaseHandler):
# XXX Should rewrite do_open() to use the new httplib interface,
# would would be a little simpler.
def do_open(self, http_class, req): def do_open(self, http_class, req):
host = req.get_host() host = req.get_host()
if not host: if not host:
raise URLError('no host given') raise URLError('no host given')
try: h = http_class(host) # will parse host:port
h = http_class(host) # will parse host:port if req.has_data():
if req.has_data(): data = req.get_data()
data = req.get_data() h.putrequest('POST', req.get_selector())
h.putrequest('POST', req.get_selector()) if not 'Content-type' in req.headers:
if not 'Content-type' in req.headers: h.putheader('Content-type',
h.putheader('Content-type', 'application/x-www-form-urlencoded')
'application/x-www-form-urlencoded') if not 'Content-length' in req.headers:
if not 'Content-length' in req.headers: h.putheader('Content-length', '%d' % len(data))
h.putheader('Content-length', '%d' % len(data)) else:
else: h.putrequest('GET', req.get_selector())
h.putrequest('GET', req.get_selector())
except socket.error, err:
raise URLError(err)
scheme, sel = splittype(req.get_selector()) scheme, sel = splittype(req.get_selector())
sel_host, sel_path = splithost(sel) sel_host, sel_path = splithost(sel)
...@@ -806,7 +817,10 @@ class AbstractHTTPHandler(BaseHandler): ...@@ -806,7 +817,10 @@ class AbstractHTTPHandler(BaseHandler):
h.putheader(*args) h.putheader(*args)
for k, v in req.headers.items(): for k, v in req.headers.items():
h.putheader(k, v) h.putheader(k, v)
h.endheaders() try:
h.endheaders()
except socket.error, err:
raise URLError(err)
if req.has_data(): if req.has_data():
h.send(data) h.send(data)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment