Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/urllib3/request.py: 39%
46 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:51 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:51 +0000
1from __future__ import absolute_import
3import sys
5from .filepost import encode_multipart_formdata
6from .packages import six
7from .packages.six.moves.urllib.parse import urlencode
9__all__ = ["RequestMethods"]
12class RequestMethods(object):
13 """
14 Convenience mixin for classes who implement a :meth:`urlopen` method, such
15 as :class:`urllib3.HTTPConnectionPool` and
16 :class:`urllib3.PoolManager`.
18 Provides behavior for making common types of HTTP request methods and
19 decides which type of request field encoding to use.
21 Specifically,
23 :meth:`.request_encode_url` is for sending requests whose fields are
24 encoded in the URL (such as GET, HEAD, DELETE).
26 :meth:`.request_encode_body` is for sending requests whose fields are
27 encoded in the *body* of the request using multipart or www-form-urlencoded
28 (such as for POST, PUT, PATCH).
30 :meth:`.request` is for making any kind of request, it will look up the
31 appropriate encoding format and use one of the above two methods to make
32 the request.
34 Initializer parameters:
36 :param headers:
37 Headers to include with all requests, unless other headers are given
38 explicitly.
39 """
41 _encode_url_methods = {"DELETE", "GET", "HEAD", "OPTIONS"}
43 def __init__(self, headers=None):
44 self.headers = headers or {}
46 def urlopen(
47 self,
48 method,
49 url,
50 body=None,
51 headers=None,
52 encode_multipart=True,
53 multipart_boundary=None,
54 **kw
55 ): # Abstract
56 raise NotImplementedError(
57 "Classes extending RequestMethods must implement "
58 "their own ``urlopen`` method."
59 )
61 def request(self, method, url, fields=None, headers=None, **urlopen_kw):
62 """
63 Make a request using :meth:`urlopen` with the appropriate encoding of
64 ``fields`` based on the ``method`` used.
66 This is a convenience method that requires the least amount of manual
67 effort. It can be used in most situations, while still having the
68 option to drop down to more specific methods when necessary, such as
69 :meth:`request_encode_url`, :meth:`request_encode_body`,
70 or even the lowest level :meth:`urlopen`.
71 """
72 method = method.upper()
74 urlopen_kw["request_url"] = url
76 if method in self._encode_url_methods:
77 return self.request_encode_url(
78 method, url, fields=fields, headers=headers, **urlopen_kw
79 )
80 else:
81 return self.request_encode_body(
82 method, url, fields=fields, headers=headers, **urlopen_kw
83 )
85 def request_encode_url(self, method, url, fields=None, headers=None, **urlopen_kw):
86 """
87 Make a request using :meth:`urlopen` with the ``fields`` encoded in
88 the url. This is useful for request methods like GET, HEAD, DELETE, etc.
89 """
90 if headers is None:
91 headers = self.headers
93 extra_kw = {"headers": headers}
94 extra_kw.update(urlopen_kw)
96 if fields:
97 url += "?" + urlencode(fields)
99 return self.urlopen(method, url, **extra_kw)
101 def request_encode_body(
102 self,
103 method,
104 url,
105 fields=None,
106 headers=None,
107 encode_multipart=True,
108 multipart_boundary=None,
109 **urlopen_kw
110 ):
111 """
112 Make a request using :meth:`urlopen` with the ``fields`` encoded in
113 the body. This is useful for request methods like POST, PUT, PATCH, etc.
115 When ``encode_multipart=True`` (default), then
116 :func:`urllib3.encode_multipart_formdata` is used to encode
117 the payload with the appropriate content type. Otherwise
118 :func:`urllib.parse.urlencode` is used with the
119 'application/x-www-form-urlencoded' content type.
121 Multipart encoding must be used when posting files, and it's reasonably
122 safe to use it in other times too. However, it may break request
123 signing, such as with OAuth.
125 Supports an optional ``fields`` parameter of key/value strings AND
126 key/filetuple. A filetuple is a (filename, data, MIME type) tuple where
127 the MIME type is optional. For example::
129 fields = {
130 'foo': 'bar',
131 'fakefile': ('foofile.txt', 'contents of foofile'),
132 'realfile': ('barfile.txt', open('realfile').read()),
133 'typedfile': ('bazfile.bin', open('bazfile').read(),
134 'image/jpeg'),
135 'nonamefile': 'contents of nonamefile field',
136 }
138 When uploading a file, providing a filename (the first parameter of the
139 tuple) is optional but recommended to best mimic behavior of browsers.
141 Note that if ``headers`` are supplied, the 'Content-Type' header will
142 be overwritten because it depends on the dynamic random boundary string
143 which is used to compose the body of the request. The random boundary
144 string can be explicitly set with the ``multipart_boundary`` parameter.
145 """
146 if headers is None:
147 headers = self.headers
149 extra_kw = {"headers": {}}
151 if fields:
152 if "body" in urlopen_kw:
153 raise TypeError(
154 "request got values for both 'fields' and 'body', can only specify one."
155 )
157 if encode_multipart:
158 body, content_type = encode_multipart_formdata(
159 fields, boundary=multipart_boundary
160 )
161 else:
162 body, content_type = (
163 urlencode(fields),
164 "application/x-www-form-urlencoded",
165 )
167 extra_kw["body"] = body
168 extra_kw["headers"] = {"Content-Type": content_type}
170 extra_kw["headers"].update(headers)
171 extra_kw.update(urlopen_kw)
173 return self.urlopen(method, url, **extra_kw)
176if not six.PY2:
178 class RequestModule(sys.modules[__name__].__class__):
179 def __call__(self, *args, **kwargs):
180 """
181 If user tries to call this module directly urllib3 v2.x style raise an error to the user
182 suggesting they may need urllib3 v2
183 """
184 raise TypeError(
185 "'module' object is not callable\n"
186 "urllib3.request() method is not supported in this release, "
187 "upgrade to urllib3 v2 to use it\n"
188 "see https://urllib3.readthedocs.io/en/stable/v2-migration-guide.html"
189 )
191 sys.modules[__name__].__class__ = RequestModule