Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit de49d64

Browse files
committed
Fix closes issue 1673007 urllib.request to support HEAD requests with a new method arg.
1 parent d8886fc commit de49d64

5 files changed

Lines changed: 72 additions & 9 deletions

File tree

Doc/library/urllib.request.rst

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,16 @@ The :mod:`urllib.request` module defines the following functions:
132132

133133
The following classes are provided:
134134

135-
.. class:: Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False)
135+
.. class:: Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
136136

137137
This class is an abstraction of a URL request.
138138

139139
*url* should be a string containing a valid URL.
140140

141141
*data* may be a string specifying additional data to send to the
142142
server, or ``None`` if no such data is needed. Currently HTTP
143-
requests are the only ones that use *data*; the HTTP request will
144-
be a POST instead of a GET when the *data* parameter is provided.
143+
requests are the only ones that use *data*, in order to choose between
144+
``'GET'`` and ``'POST'`` when *method* is not specified.
145145
*data* should be a buffer in the standard
146146
:mimetype:`application/x-www-form-urlencoded` format. The
147147
:func:`urllib.parse.urlencode` function takes a mapping or sequence
@@ -157,8 +157,8 @@ The following classes are provided:
157157
:mod:`urllib`'s default user agent string is
158158
``"Python-urllib/2.6"`` (on Python 2.6).
159159

160-
The final two arguments are only of interest for correct handling
161-
of third-party HTTP cookies:
160+
The following two arguments, *origin_req_host* and *unverifiable*,
161+
are only of interest for correct handling of third-party HTTP cookies:
162162

163163
*origin_req_host* should be the request-host of the origin
164164
transaction, as defined by :rfc:`2965`. It defaults to
@@ -175,6 +175,13 @@ The following classes are provided:
175175
document, and the user had no option to approve the automatic
176176
fetching of the image, this should be true.
177177

178+
*method* should be a string that indicates the HTTP request method that
179+
will be used (e.g. ``'HEAD'``). Its value is stored in the
180+
:attr:`Request.method` attribute and is used by :meth:`Request.get_method()`.
181+
182+
.. versionchanged:: 3.3
183+
:attr:`Request.method` argument is added to the Request class.
184+
178185

179186
.. class:: OpenerDirector()
180187

@@ -369,6 +376,15 @@ request.
369376
boolean, indicates whether the request is unverifiable as defined
370377
by RFC 2965.
371378

379+
.. attribute:: Request.method
380+
381+
The HTTP request method to use. This value is used by
382+
:meth:`Request.get_method` to override the computed HTTP request
383+
method that would otherwise be returned. This attribute is
384+
initialized with the value of the *method* argument passed to the constructor.
385+
386+
..versionadded:: 3.3
387+
372388
.. method:: Request.add_data(data)
373389

374390
Set the :class:`Request` data to *data*. This is ignored by all handlers except
@@ -378,8 +394,13 @@ request.
378394

379395
.. method:: Request.get_method()
380396

381-
Return a string indicating the HTTP request method. This is only meaningful for
382-
HTTP requests, and currently always returns ``'GET'`` or ``'POST'``.
397+
Return a string indicating the HTTP request method. If
398+
:attr:`Request.method` is not ``None``, return its value, otherwise return
399+
``'GET'`` if :attr:`Request.data` is ``None``, or ``'POST'`` if it's not.
400+
This is only meaningful for HTTP requests.
401+
402+
.. versionchanged:: 3.3
403+
get_method now looks at the value of :attr:`Request.method` first.
383404

384405

385406
.. method:: Request.has_data()

Doc/whatsnew/3.3.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,16 @@ shutil
474474
path also specifying the user/group names and not only their numeric
475475
ids. (Contributed by Sandro Tosi in :issue:`12191`)
476476

477+
urllib
478+
------
479+
480+
The :class:`~urllib.request.Request` class, now accepts a *method* argument
481+
used by :meth:`~urllib.request.Request.get_method` to determine what HTTP method
482+
should be used. For example, this will send an ``'HEAD'`` request::
483+
484+
>>> urlopen(Request('http://www.python.org', method='HEAD'))
485+
486+
(:issue:`1673007`)
477487

478488
Optimizations
479489
=============

Lib/test/test_urllib.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,28 @@ def open_spam(self, url):
11571157
# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
11581158
# ftp.close()
11591159

1160+
class RequestTests(unittest.TestCase):
1161+
"""Unit tests for urllib.request.Request."""
1162+
1163+
def test_default_values(self):
1164+
Request = urllib.request.Request
1165+
request = Request("http://www.python.org")
1166+
self.assertEqual(request.get_method(), 'GET')
1167+
request = Request("http://www.python.org", {})
1168+
self.assertEqual(request.get_method(), 'POST')
1169+
1170+
def test_with_method_arg(self):
1171+
Request = urllib.request.Request
1172+
request = Request("http://www.python.org", method='HEAD')
1173+
self.assertEqual(request.method, 'HEAD')
1174+
self.assertEqual(request.get_method(), 'HEAD')
1175+
request = Request("http://www.python.org", {}, method='HEAD')
1176+
self.assertEqual(request.method, 'HEAD')
1177+
self.assertEqual(request.get_method(), 'HEAD')
1178+
request = Request("http://www.python.org", method='GET')
1179+
self.assertEqual(request.get_method(), 'GET')
1180+
request.method = 'HEAD'
1181+
self.assertEqual(request.get_method(), 'HEAD')
11601182

11611183

11621184
def test_main():
@@ -1172,6 +1194,7 @@ def test_main():
11721194
Utility_Tests,
11731195
URLopener_Tests,
11741196
#FTPWrapperTests,
1197+
RequestTests,
11751198
)
11761199

11771200

Lib/urllib/request.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ def request_host(request):
177177
class Request:
178178

179179
def __init__(self, url, data=None, headers={},
180-
origin_req_host=None, unverifiable=False):
180+
origin_req_host=None, unverifiable=False,
181+
method=None):
181182
# unwrap('<URL:type://host/path>') --> 'type://host/path'
182183
self.full_url = unwrap(url)
183184
self.full_url, self.fragment = splittag(self.full_url)
@@ -191,6 +192,7 @@ def __init__(self, url, data=None, headers={},
191192
origin_req_host = request_host(self)
192193
self.origin_req_host = origin_req_host
193194
self.unverifiable = unverifiable
195+
self.method = method
194196
self._parse()
195197

196198
def _parse(self):
@@ -202,7 +204,10 @@ def _parse(self):
202204
self.host = unquote(self.host)
203205

204206
def get_method(self):
205-
if self.data is not None:
207+
"""Return a string indicating the HTTP request method."""
208+
if self.method is not None:
209+
return self.method
210+
elif self.data is not None:
206211
return "POST"
207212
else:
208213
return "GET"

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ Core and Builtins
304304

305305
Library
306306
-------
307+
308+
- issue #1673007: urllib2 to support HEAD request via new method argument.
309+
Patch contributions by David Stanek, Patrick Westerhoff and Ezio Melotti.
310+
307311
- Issue #12386: packaging does not fail anymore when writing the RESOURCES
308312
file.
309313

0 commit comments

Comments
 (0)