Commit de49d64d authored by Senthil Kumaran's avatar Senthil Kumaran

Fix closes issue 1673007 urllib.request to support HEAD requests with a new method arg.

parent d8886fc8
...@@ -132,7 +132,7 @@ The :mod:`urllib.request` module defines the following functions: ...@@ -132,7 +132,7 @@ The :mod:`urllib.request` module defines the following functions:
The following classes are provided: The following classes are provided:
.. class:: Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False) .. class:: Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
This class is an abstraction of a URL request. This class is an abstraction of a URL request.
...@@ -140,8 +140,8 @@ The following classes are provided: ...@@ -140,8 +140,8 @@ The following classes are provided:
*data* may be a string specifying additional data to send to the *data* may be a string specifying additional data to send to the
server, or ``None`` if no such data is needed. Currently HTTP server, or ``None`` if no such data is needed. Currently HTTP
requests are the only ones that use *data*; the HTTP request will requests are the only ones that use *data*, in order to choose between
be a POST instead of a GET when the *data* parameter is provided. ``'GET'`` and ``'POST'`` when *method* is not specified.
*data* should be a buffer in the standard *data* should be a buffer in the standard
:mimetype:`application/x-www-form-urlencoded` format. The :mimetype:`application/x-www-form-urlencoded` format. The
:func:`urllib.parse.urlencode` function takes a mapping or sequence :func:`urllib.parse.urlencode` function takes a mapping or sequence
...@@ -157,8 +157,8 @@ The following classes are provided: ...@@ -157,8 +157,8 @@ The following classes are provided:
:mod:`urllib`'s default user agent string is :mod:`urllib`'s default user agent string is
``"Python-urllib/2.6"`` (on Python 2.6). ``"Python-urllib/2.6"`` (on Python 2.6).
The final two arguments are only of interest for correct handling The following two arguments, *origin_req_host* and *unverifiable*,
of third-party HTTP cookies: are only of interest for correct handling of third-party HTTP cookies:
*origin_req_host* should be the request-host of the origin *origin_req_host* should be the request-host of the origin
transaction, as defined by :rfc:`2965`. It defaults to transaction, as defined by :rfc:`2965`. It defaults to
...@@ -175,6 +175,13 @@ The following classes are provided: ...@@ -175,6 +175,13 @@ The following classes are provided:
document, and the user had no option to approve the automatic document, and the user had no option to approve the automatic
fetching of the image, this should be true. fetching of the image, this should be true.
*method* should be a string that indicates the HTTP request method that
will be used (e.g. ``'HEAD'``). Its value is stored in the
:attr:`Request.method` attribute and is used by :meth:`Request.get_method()`.
.. versionchanged:: 3.3
:attr:`Request.method` argument is added to the Request class.
.. class:: OpenerDirector() .. class:: OpenerDirector()
...@@ -369,6 +376,15 @@ request. ...@@ -369,6 +376,15 @@ request.
boolean, indicates whether the request is unverifiable as defined boolean, indicates whether the request is unverifiable as defined
by RFC 2965. by RFC 2965.
.. attribute:: Request.method
The HTTP request method to use. This value is used by
:meth:`Request.get_method` to override the computed HTTP request
method that would otherwise be returned. This attribute is
initialized with the value of the *method* argument passed to the constructor.
..versionadded:: 3.3
.. method:: Request.add_data(data) .. method:: Request.add_data(data)
Set the :class:`Request` data to *data*. This is ignored by all handlers except Set the :class:`Request` data to *data*. This is ignored by all handlers except
...@@ -378,8 +394,13 @@ request. ...@@ -378,8 +394,13 @@ request.
.. method:: Request.get_method() .. method:: Request.get_method()
Return a string indicating the HTTP request method. This is only meaningful for Return a string indicating the HTTP request method. If
HTTP requests, and currently always returns ``'GET'`` or ``'POST'``. :attr:`Request.method` is not ``None``, return its value, otherwise return
``'GET'`` if :attr:`Request.data` is ``None``, or ``'POST'`` if it's not.
This is only meaningful for HTTP requests.
.. versionchanged:: 3.3
get_method now looks at the value of :attr:`Request.method` first.
.. method:: Request.has_data() .. method:: Request.has_data()
......
...@@ -474,6 +474,16 @@ shutil ...@@ -474,6 +474,16 @@ shutil
path also specifying the user/group names and not only their numeric path also specifying the user/group names and not only their numeric
ids. (Contributed by Sandro Tosi in :issue:`12191`) ids. (Contributed by Sandro Tosi in :issue:`12191`)
urllib
------
The :class:`~urllib.request.Request` class, now accepts a *method* argument
used by :meth:`~urllib.request.Request.get_method` to determine what HTTP method
should be used. For example, this will send an ``'HEAD'`` request::
>>> urlopen(Request('http://www.python.org', method='HEAD'))
(:issue:`1673007`)
Optimizations Optimizations
============= =============
......
...@@ -1157,6 +1157,28 @@ class URLopener_Tests(unittest.TestCase): ...@@ -1157,6 +1157,28 @@ class URLopener_Tests(unittest.TestCase):
# self.assertEqual(ftp.ftp.sock.gettimeout(), 30) # self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
# ftp.close() # ftp.close()
class RequestTests(unittest.TestCase):
"""Unit tests for urllib.request.Request."""
def test_default_values(self):
Request = urllib.request.Request
request = Request("http://www.python.org")
self.assertEqual(request.get_method(), 'GET')
request = Request("http://www.python.org", {})
self.assertEqual(request.get_method(), 'POST')
def test_with_method_arg(self):
Request = urllib.request.Request
request = Request("http://www.python.org", method='HEAD')
self.assertEqual(request.method, 'HEAD')
self.assertEqual(request.get_method(), 'HEAD')
request = Request("http://www.python.org", {}, method='HEAD')
self.assertEqual(request.method, 'HEAD')
self.assertEqual(request.get_method(), 'HEAD')
request = Request("http://www.python.org", method='GET')
self.assertEqual(request.get_method(), 'GET')
request.method = 'HEAD'
self.assertEqual(request.get_method(), 'HEAD')
def test_main(): def test_main():
...@@ -1172,6 +1194,7 @@ def test_main(): ...@@ -1172,6 +1194,7 @@ def test_main():
Utility_Tests, Utility_Tests,
URLopener_Tests, URLopener_Tests,
#FTPWrapperTests, #FTPWrapperTests,
RequestTests,
) )
......
...@@ -177,7 +177,8 @@ def request_host(request): ...@@ -177,7 +177,8 @@ def request_host(request):
class Request: class Request:
def __init__(self, url, data=None, headers={}, def __init__(self, url, data=None, headers={},
origin_req_host=None, unverifiable=False): origin_req_host=None, unverifiable=False,
method=None):
# unwrap('<URL:type://host/path>') --> 'type://host/path' # unwrap('<URL:type://host/path>') --> 'type://host/path'
self.full_url = unwrap(url) self.full_url = unwrap(url)
self.full_url, self.fragment = splittag(self.full_url) self.full_url, self.fragment = splittag(self.full_url)
...@@ -191,6 +192,7 @@ class Request: ...@@ -191,6 +192,7 @@ class Request:
origin_req_host = request_host(self) origin_req_host = request_host(self)
self.origin_req_host = origin_req_host self.origin_req_host = origin_req_host
self.unverifiable = unverifiable self.unverifiable = unverifiable
self.method = method
self._parse() self._parse()
def _parse(self): def _parse(self):
...@@ -202,7 +204,10 @@ class Request: ...@@ -202,7 +204,10 @@ class Request:
self.host = unquote(self.host) self.host = unquote(self.host)
def get_method(self): def get_method(self):
if self.data is not None: """Return a string indicating the HTTP request method."""
if self.method is not None:
return self.method
elif self.data is not None:
return "POST" return "POST"
else: else:
return "GET" return "GET"
......
...@@ -304,6 +304,10 @@ Core and Builtins ...@@ -304,6 +304,10 @@ Core and Builtins
Library Library
------- -------
- issue #1673007: urllib2 to support HEAD request via new method argument.
Patch contributions by David Stanek, Patrick Westerhoff and Ezio Melotti.
- Issue #12386: packaging does not fail anymore when writing the RESOURCES - Issue #12386: packaging does not fail anymore when writing the RESOURCES
file. file.
......
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