diff --git a/test/with_dummyserver/test_poolmanager.py b/test/with_dummyserver/test_poolmanager.py index 26c80448de..b545705c44 100644 --- a/test/with_dummyserver/test_poolmanager.py +++ b/test/with_dummyserver/test_poolmanager.py @@ -84,8 +84,17 @@ def test_headers(self): self.assertEqual(returned_headers.get('Foo'), None) self.assertEqual(returned_headers.get('Baz'), 'quux') + r = http.request_encode_body('GET', '%s/headers' % self.base_url, skip_accept_encoding=True) + returned_headers = json.loads(r.data.decode()) + header_keys = [header_key.lower() for header_key in returned_headers.keys()] + self.assertNotIn("accept-encoding", header_keys) + self.assertIn("host", header_keys) - + r = http.request_encode_body('GET', '%s/headers' % self.base_url, skip_host=True) + returned_headers = json.loads(r.data.decode()) + header_keys = [header_key.lower() for header_key in returned_headers.keys()] + self.assertIn("accept-encoding", header_keys) + self.assertNotIn("host", header_keys) if __name__ == '__main__': unittest.main() diff --git a/urllib3/connectionpool.py b/urllib3/connectionpool.py index af8760dc70..4a6a66b7fa 100644 --- a/urllib3/connectionpool.py +++ b/urllib3/connectionpool.py @@ -10,36 +10,29 @@ from socket import error as SocketError, timeout as SocketTimeout -try: # Python 3 - from http.client import HTTPConnection, HTTPException - from http.client import HTTP_PORT, HTTPS_PORT -except ImportError: - from httplib import HTTPConnection, HTTPException - from httplib import HTTP_PORT, HTTPS_PORT +from .httpconnection import (HTTPConnection, + HTTPException, + HTTP_PORT, + HTTPS_PORT, +) try: # Python 3 from queue import LifoQueue, Empty, Full except ImportError: from Queue import LifoQueue, Empty, Full - try: # Compiled with SSL? HTTPSConnection = object BaseSSLError = None ssl = None - try: # Python 3 - from http.client import HTTPSConnection - except ImportError: - from httplib import HTTPSConnection + from httpconnection import HTTPSConnection import ssl BaseSSLError = ssl.SSLError - except (ImportError, AttributeError): # Platform-specific: No SSL. pass - from .request import RequestMethods from .response import HTTPResponse from .util import get_host, is_connection_dropped, ssl_wrap_socket @@ -325,6 +318,8 @@ def is_same_host(self, url): def urlopen(self, method, url, body=None, headers=None, retries=3, redirect=True, assert_same_host=True, timeout=_Default, + skip_host=False, + skip_accept_encoding=False, pool_timeout=None, release_conn=None, **response_kw): """ Get a connection from the pool and perform an HTTP request. This is the @@ -386,6 +381,12 @@ def urlopen(self, method, url, body=None, headers=None, retries=3, back into the pool. If None, it takes the value of ``response_kw.get('preload_content', True)``. + :param skip_host: + If ``True``, the default "Host" header will not be set. + + :param skip_accept_encoding: + If ``True``, the default "Accept-Encoding" header will not be set. + :param \**response_kw: Additional parameters are passed to :meth:`urllib3.response.HTTPResponse.from_httplib` @@ -419,6 +420,8 @@ def urlopen(self, method, url, body=None, headers=None, retries=3, # Make the request on the httplib connection object httplib_response = self._make_request(conn, method, url, timeout=timeout, + skip_host=skip_host, + skip_accept_encoding=skip_accept_encoding, body=body, headers=headers) # If we're going to release the connection in ``finally:``, then @@ -479,6 +482,8 @@ def urlopen(self, method, url, body=None, headers=None, retries=3, return self.urlopen(method, url, body, headers, retries - 1, redirect, assert_same_host, timeout=timeout, pool_timeout=pool_timeout, + skip_host=skip_host, + skip_accept_encoding=skip_accept_encoding, release_conn=release_conn, **response_kw) # Handle redirect? @@ -490,6 +495,8 @@ def urlopen(self, method, url, body=None, headers=None, retries=3, return self.urlopen(method, redirect_location, body, headers, retries - 1, redirect, assert_same_host, timeout=timeout, pool_timeout=pool_timeout, + skip_host=skip_host, + skip_accept_encoding=skip_accept_encoding, release_conn=release_conn, **response_kw) return response diff --git a/urllib3/httpconnection.py b/urllib3/httpconnection.py new file mode 100644 index 0000000000..85cc0488f9 --- /dev/null +++ b/urllib3/httpconnection.py @@ -0,0 +1,50 @@ +# urllib3/httpconnection.py +# Copyright 2008-2012 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +try: # Python 3 + from http.client import HTTPConnection, HTTPException + from http.client import HTTP_PORT, HTTPS_PORT +except ImportError: + from httplib import HTTPConnection, HTTPException + from httplib import HTTP_PORT, HTTPS_PORT + +class SkipFriendlyHTTPConnection(HTTPConnection): + def request(self, method, url, body=None, skip_host=False, skip_accept_encoding=False, headers={}): + """Send a complete request to the server.""" + self._send_request(method, url, body, headers, skip_host=skip_host, skip_accept_encoding=skip_accept_encoding) + + def _send_request(self, method, url, body, headers, skip_host=False, skip_accept_encoding=False): + header_names = dict.fromkeys([k.lower() for k in headers]) + skips = {} + # enable skip_host and skip_accept_encoding from py2.4 + if skip_host or ('host' in header_names): + skips['skip_host'] = 1 + if skip_accept_encoding or ('accept-encoding' in header_names): + skips['skip_accept_encoding'] = 1 + + self.putrequest(method, url, **skips) + + if body is not None and ('content-length' not in header_names): + self._set_content_length(body) + for hdr, value in headers.items(): + self.putheader(hdr, value) + if isinstance(body, str): + # RFC 2616 Section 3.7.1 says that text default has a + # default charset of iso-8859-1. + body = body.encode('iso-8859-1') + self.endheaders(body) +HTTPConnection = SkipFriendlyHTTPConnection + +try: # Compiled with SSL? + try: # Python 3 + from http.client import HTTPSConnection + except ImportError: + from httplib import HTTPSConnection + + class SkipFriendlyHTTPSConnection(SkipFriendlyHTTPConnection): pass + HTTPSConnection = SkipFriendlyHTTPSConnection +except (ImportError, AttributeError): + pass