Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c0ae48b

Browse filesBrowse files
committed
py3: Stop using stdlib's putrequest(); it only does ASCII
Note that this only affects the functest client. See also: https://bugs.python.org/issue36274 Change-Id: I1359c475fbe93db2f0fcc4b450be6dd5073f922e
1 parent 93b49c5 commit c0ae48b
Copy full SHA for c0ae48b

1 file changed

+87Lines changed: 87 additions & 0 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎test/functional/swift_test_client.py‎

Copy file name to clipboardExpand all lines: test/functional/swift_test_client.py
+87Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,91 @@ def listing_items(method):
111111
items = []
112112

113113

114+
def putrequest(self, method, url, skip_host=False, skip_accept_encoding=False):
115+
'''Send a request to the server.
116+
117+
This is mostly a regurgitation of CPython's HTTPConnection.putrequest,
118+
but fixed up so we can still send arbitrary bytes in the request line
119+
on py3. See also: https://bugs.python.org/issue36274
120+
121+
To use, swap out a HTTP(S)Connection's putrequest with something like::
122+
123+
conn.putrequest = putrequest.__get__(conn)
124+
125+
:param method: specifies an HTTP request method, e.g. 'GET'.
126+
:param url: specifies the object being requested, e.g. '/index.html'.
127+
:param skip_host: if True does not add automatically a 'Host:' header
128+
:param skip_accept_encoding: if True does not add automatically an
129+
'Accept-Encoding:' header
130+
'''
131+
# (Mostly) inline the HTTPConnection implementation; just fix it
132+
# so we can send non-ascii request lines. For comparison, see
133+
# https://github.com/python/cpython/blob/v2.7.16/Lib/httplib.py#L888-L1003
134+
# and https://github.com/python/cpython/blob/v3.7.2/
135+
# Lib/http/client.py#L1061-L1183
136+
if self._HTTPConnection__response \
137+
and self._HTTPConnection__response.isclosed():
138+
self._HTTPConnection__response = None
139+
140+
if self._HTTPConnection__state == http_client._CS_IDLE:
141+
self._HTTPConnection__state = http_client._CS_REQ_STARTED
142+
else:
143+
raise http_client.CannotSendRequest(self._HTTPConnection__state)
144+
145+
self._method = method
146+
if not url:
147+
url = '/'
148+
self._path = url
149+
request = '%s %s %s' % (method, url, self._http_vsn_str)
150+
if not isinstance(request, bytes):
151+
# This choice of encoding is the whole reason we copy/paste from
152+
# cpython. When making backend requests, it should never be
153+
# necessary; however, we have some functional tests that want
154+
# to send non-ascii bytes.
155+
# TODO: when https://bugs.python.org/issue36274 is resolved, make
156+
# sure we fix up our API to match whatever upstream chooses to do
157+
self._output(request.encode('latin1'))
158+
else:
159+
self._output(request)
160+
161+
if self._http_vsn == 11:
162+
if not skip_host:
163+
netloc = ''
164+
if url.startswith('http'):
165+
nil, netloc, nil, nil, nil = urllib.parse.urlsplit(url)
166+
167+
if netloc:
168+
try:
169+
netloc_enc = netloc.encode("ascii")
170+
except UnicodeEncodeError:
171+
netloc_enc = netloc.encode("idna")
172+
self.putheader('Host', netloc_enc)
173+
else:
174+
if self._tunnel_host:
175+
host = self._tunnel_host
176+
port = self._tunnel_port
177+
else:
178+
host = self.host
179+
port = self.port
180+
181+
try:
182+
host_enc = host.encode("ascii")
183+
except UnicodeEncodeError:
184+
host_enc = host.encode("idna")
185+
186+
if host.find(':') >= 0:
187+
host_enc = b'[' + host_enc + b']'
188+
189+
if port == self.default_port:
190+
self.putheader('Host', host_enc)
191+
else:
192+
host_enc = host_enc.decode("ascii")
193+
self.putheader('Host', "%s:%s" % (host_enc, port))
194+
195+
if not skip_accept_encoding:
196+
self.putheader('Accept-Encoding', 'identity')
197+
198+
114199
class Connection(object):
115200
def __init__(self, config):
116201
for key in 'auth_host auth_port auth_ssl username password'.split():
@@ -132,6 +217,7 @@ def __init__(self, config):
132217
self.storage_netloc = None
133218
self.storage_path = None
134219
self.conn_class = None
220+
self.connection = None # until you call .http_connect()
135221

136222
@property
137223
def storage_url(self):
@@ -235,6 +321,7 @@ def http_connect(self):
235321
context=ssl._create_unverified_context())
236322
else:
237323
self.connection = self.conn_class(self.storage_netloc)
324+
self.connection.putrequest = putrequest.__get__(self.connection)
238325

239326
def make_path(self, path=None, cfg=None):
240327
if path is None:

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.