From b3ee6f9921a0979b77a64b83f2f3a267ae66916e Mon Sep 17 00:00:00 2001 From: Jeremy Hylton Date: Tue, 24 Feb 2004 19:40:35 +0000 Subject: [PATCH] Fix two bugs in the new do_open() implementation for HTTPHandler. Invoke the standard error handlers for non-200 responses. Always supply a "Connection: close" header to prevent the server from leaving the connection open. Downstream users of the socket may attempt recv()/read() with no arguments, which would block if the connection were kept open. --- Lib/test/test_urllib2.py | 3 ++- Lib/urllib2.py | 23 +++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py index 87de2297685..f38a4a3f400 100644 --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -461,7 +461,8 @@ class HandlerTests(unittest.TestCase): self.assertEqual(http.method, method) self.assertEqual(http.selector, "/") self.assertEqual(http.req_headers, - [("Foo", "bar"), ("Spam", "eggs")]) + [("Connection", "close"), + ("Foo", "bar"), ("Spam", "eggs")]) self.assertEqual(http.data, data) # check socket.error converted to URLError diff --git a/Lib/urllib2.py b/Lib/urllib2.py index 9f6dc6309f0..cd0cfc18e17 100644 --- a/Lib/urllib2.py +++ b/Lib/urllib2.py @@ -957,18 +957,29 @@ class AbstractHTTPHandler(BaseHandler): headers = dict(req.headers) headers.update(req.unredirected_hdrs) + # We want to make an HTTP/1.1 request, but the addinfourl + # class isn't prepared to deal with a persistent connection. + # It will try to read all remaining data from the socket, + # which will block while the server waits for the next request. + # So make sure the connection gets closed after the (only) + # request. + headers["Connection"] = "close" try: h.request(req.get_method(), req.get_selector(), req.data, headers) r = h.getresponse() except socket.error, err: # XXX what error? raise URLError(err) - # Pick apart the HTTPResponse object to get the various pieces - # of the - resp = addinfourl(r.fp, r.msg, req.get_full_url()) - resp.code = r.status - resp.msg = r.reason - return resp + if r.status == 200: + # Pick apart the HTTPResponse object to get the addinfourl + # object initialized properly + resp = addinfourl(r.fp, r.msg, req.get_full_url()) + resp.code = r.status + resp.msg = r.reason + return resp + else: + return self.parent.error("http", req, r.fp, r.status, r.msg, + r.msg.dict) class HTTPHandler(AbstractHTTPHandler):