Kaydet (Commit) 2933312f authored tarafından Senthil Kumaran's avatar Senthil Kumaran

Fixed issue11082 - Reject str for POST data with a TypeError. Document the need…

Fixed issue11082 - Reject str for POST data with a TypeError. Document the need to explicitly encode to bytes when using urlencode.
üst 44028d86
...@@ -140,6 +140,7 @@ or on combining URL components into a URL string. ...@@ -140,6 +140,7 @@ or on combining URL components into a URL string.
Use the :func:`urllib.parse.urlencode` function to convert such Use the :func:`urllib.parse.urlencode` function to convert such
dictionaries into query strings. dictionaries into query strings.
.. versionchanged:: 3.2 .. versionchanged:: 3.2
Add *encoding* and *errors* parameters. Add *encoding* and *errors* parameters.
...@@ -506,9 +507,10 @@ task isn't already covered by the URL parsing functions above. ...@@ -506,9 +507,10 @@ task isn't already covered by the URL parsing functions above.
.. function:: urlencode(query, doseq=False, safe='', encoding=None, errors=None) .. function:: urlencode(query, doseq=False, safe='', encoding=None, errors=None)
Convert a mapping object or a sequence of two-element tuples, which may Convert a mapping object or a sequence of two-element tuples, which may
either be a :class:`str` or a :class:`bytes`, to a "percent-encoded" string, either be a :class:`str` or a :class:`bytes`, to a "percent-encoded"
suitable to pass to :func:`urlopen` above as the optional *data* argument. string. The resultant string must be converted to bytes using the
This is useful to pass a dictionary of form fields to a ``POST`` request. user-specified encoding before it is sent to :func:`urlopen` as the optional
*data* argument.
The resulting string is a series of ``key=value`` pairs separated by ``'&'`` The resulting string is a series of ``key=value`` pairs separated by ``'&'``
characters, where both *key* and *value* are quoted using :func:`quote_plus` characters, where both *key* and *value* are quoted using :func:`quote_plus`
above. When a sequence of two-element tuples is used as the *query* above. When a sequence of two-element tuples is used as the *query*
...@@ -525,6 +527,9 @@ task isn't already covered by the URL parsing functions above. ...@@ -525,6 +527,9 @@ task isn't already covered by the URL parsing functions above.
To reverse this encoding process, :func:`parse_qs` and :func:`parse_qsl` are To reverse this encoding process, :func:`parse_qs` and :func:`parse_qsl` are
provided in this module to parse query strings into Python data structures. provided in this module to parse query strings into Python data structures.
Refer to :ref:`urllib examples <urllib-examples>` to find out how urlencode
method can be used for generating query string for a URL or data for POST.
.. versionchanged:: 3.2 .. versionchanged:: 3.2
Query parameter supports bytes and string objects. Query parameter supports bytes and string objects.
......
...@@ -967,7 +967,7 @@ when the Python installation supports SSL. :: ...@@ -967,7 +967,7 @@ when the Python installation supports SSL. ::
>>> import urllib.request >>> import urllib.request
>>> req = urllib.request.Request(url='https://localhost/cgi-bin/test.cgi', >>> req = urllib.request.Request(url='https://localhost/cgi-bin/test.cgi',
... data='This data is passed to stdin of the CGI') ... data=b'This data is passed to stdin of the CGI')
>>> f = urllib.request.urlopen(req) >>> f = urllib.request.urlopen(req)
>>> print(f.read().decode('utf-8')) >>> print(f.read().decode('utf-8'))
Got Data: "This data is passed to stdin of the CGI" Got Data: "This data is passed to stdin of the CGI"
...@@ -1043,11 +1043,13 @@ containing parameters:: ...@@ -1043,11 +1043,13 @@ containing parameters::
>>> f = urllib.request.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params) >>> f = urllib.request.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params)
>>> print(f.read().decode('utf-8')) >>> print(f.read().decode('utf-8'))
The following example uses the ``POST`` method instead:: The following example uses the ``POST`` method instead. Note that params output
from urlencode is encoded to bytes before it is sent to urlopen as data::
>>> import urllib.request >>> import urllib.request
>>> import urllib.parse >>> import urllib.parse
>>> params = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0}) >>> params = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> params = params.encode('utf-8')
>>> f = urllib.request.urlopen("http://www.musi-cal.com/cgi-bin/query", params) >>> f = urllib.request.urlopen("http://www.musi-cal.com/cgi-bin/query", params)
>>> print(f.read().decode('utf-8')) >>> print(f.read().decode('utf-8'))
......
...@@ -794,6 +794,10 @@ class HandlerTests(unittest.TestCase): ...@@ -794,6 +794,10 @@ class HandlerTests(unittest.TestCase):
http.raise_on_endheaders = True http.raise_on_endheaders = True
self.assertRaises(urllib.error.URLError, h.do_open, http, req) self.assertRaises(urllib.error.URLError, h.do_open, http, req)
# Check for TypeError on POST data which is str.
req = Request("http://example.com/","badpost")
self.assertRaises(TypeError, h.do_request_, req)
# check adding of standard headers # check adding of standard headers
o.addheaders = [("Spam", "eggs")] o.addheaders = [("Spam", "eggs")]
for data in b"", None: # POST, GET for data in b"", None: # POST, GET
...@@ -837,10 +841,11 @@ class HandlerTests(unittest.TestCase): ...@@ -837,10 +841,11 @@ class HandlerTests(unittest.TestCase):
else: else:
newreq = h.do_request_(req) newreq = h.do_request_(req)
# A file object # A file object.
# Test only Content-Length attribute of request.
file_obj = io.StringIO() file_obj = io.BytesIO()
file_obj.write("Something\nSomething\nSomething\n") file_obj.write(b"Something\nSomething\nSomething\n")
for headers in {}, {"Content-Length": 30}: for headers in {}, {"Content-Length": 30}:
req = Request("http://example.com/", file_obj, headers) req = Request("http://example.com/", file_obj, headers)
...@@ -863,7 +868,6 @@ class HandlerTests(unittest.TestCase): ...@@ -863,7 +868,6 @@ class HandlerTests(unittest.TestCase):
newreq = h.do_request_(req) newreq = h.do_request_(req)
self.assertEqual(int(newreq.get_header('Content-length')),16) self.assertEqual(int(newreq.get_header('Content-length')),16)
def test_http_doubleslash(self): def test_http_doubleslash(self):
# Checks the presence of any unnecessary double slash in url does not # Checks the presence of any unnecessary double slash in url does not
# break anything. Previously, a double slash directly after the host # break anything. Previously, a double slash directly after the host
......
...@@ -1048,6 +1048,9 @@ class AbstractHTTPHandler(BaseHandler): ...@@ -1048,6 +1048,9 @@ class AbstractHTTPHandler(BaseHandler):
if request.data is not None: # POST if request.data is not None: # POST
data = request.data data = request.data
if isinstance(data, str):
raise TypeError("POST data should be bytes"
" or an iterable of bytes. It cannot be str.")
if not request.has_header('Content-type'): if not request.has_header('Content-type'):
request.add_unredirected_header( request.add_unredirected_header(
'Content-type', 'Content-type',
......
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