|
@@
-1,842
+1,910
b''
|
|
1
|
# Copyright 2010, Google Inc.
|
|
1
|
# Copyright 2010, Google Inc.
|
|
2
|
# All rights reserved.
|
|
2
|
# All rights reserved.
|
|
3
|
#
|
|
3
|
#
|
|
4
|
# Redistribution and use in source and binary forms, with or without
|
|
4
|
# Redistribution and use in source and binary forms, with or without
|
|
5
|
# modification, are permitted provided that the following conditions are
|
|
5
|
# modification, are permitted provided that the following conditions are
|
|
6
|
# met:
|
|
6
|
# met:
|
|
7
|
#
|
|
7
|
#
|
|
8
|
# * Redistributions of source code must retain the above copyright
|
|
8
|
# * Redistributions of source code must retain the above copyright
|
|
9
|
# notice, this list of conditions and the following disclaimer.
|
|
9
|
# notice, this list of conditions and the following disclaimer.
|
|
10
|
# * Redistributions in binary form must reproduce the above
|
|
10
|
# * Redistributions in binary form must reproduce the above
|
|
11
|
# copyright notice, this list of conditions and the following disclaimer
|
|
11
|
# copyright notice, this list of conditions and the following disclaimer
|
|
12
|
# in the documentation and/or other materials provided with the
|
|
12
|
# in the documentation and/or other materials provided with the
|
|
13
|
# distribution.
|
|
13
|
# distribution.
|
|
14
|
# * Neither the name of Google Inc. nor the names of its
|
|
14
|
# * Neither the name of Google Inc. nor the names of its
|
|
15
|
# contributors may be used to endorse or promote products derived from
|
|
15
|
# contributors may be used to endorse or promote products derived from
|
|
16
|
# this software without specific prior written permission.
|
|
16
|
# this software without specific prior written permission.
|
|
17
|
|
|
17
|
|
|
18
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
18
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
19
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
19
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
20
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
20
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
21
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
21
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
22
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
22
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
23
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
23
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
24
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
24
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
25
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
25
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
26
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
26
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
27
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
27
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
|
"""Improved HTTP/1.1 client library
|
|
29
|
"""Improved HTTP/1.1 client library
|
|
30
|
|
|
30
|
|
|
31
|
This library contains an HTTPConnection which is similar to the one in
|
|
31
|
This library contains an HTTPConnection which is similar to the one in
|
|
32
|
httplib, but has several additional features:
|
|
32
|
httplib, but has several additional features:
|
|
33
|
|
|
33
|
|
|
34
|
* supports keepalives natively
|
|
34
|
* supports keepalives natively
|
|
35
|
* uses select() to block for incoming data
|
|
35
|
* uses select() to block for incoming data
|
|
36
|
* notices when the server responds early to a request
|
|
36
|
* notices when the server responds early to a request
|
|
37
|
* implements ssl inline instead of in a different class
|
|
37
|
* implements ssl inline instead of in a different class
|
|
38
|
"""
|
|
38
|
"""
|
|
39
|
from __future__ import absolute_import
|
|
39
|
from __future__ import absolute_import
|
|
40
|
|
|
40
|
|
|
41
|
# Many functions in this file have too many arguments.
|
|
41
|
# Many functions in this file have too many arguments.
|
|
42
|
# pylint: disable=R0913
|
|
42
|
# pylint: disable=R0913
|
|
43
|
|
|
43
|
import email
|
|
|
|
|
44
|
import email.message
|
|
44
|
import errno
|
|
45
|
import errno
|
|
45
|
import inspect
|
|
46
|
import inspect
|
|
46
|
import logging
|
|
47
|
import logging
|
|
47
|
import rfc822
|
|
|
|
|
48
|
import select
|
|
48
|
import select
|
|
49
|
import socket
|
|
49
|
import socket
|
|
|
|
|
50
|
import ssl
|
|
|
|
|
51
|
import sys
|
|
50
|
|
|
52
|
|
|
51
|
try:
|
|
53
|
try:
|
|
52
|
import cStringIO as io
|
|
54
|
import cStringIO as io
|
|
53
|
io.StringIO
|
|
55
|
io.StringIO
|
|
54
|
except ImportError:
|
|
56
|
except ImportError:
|
|
55
|
import io
|
|
57
|
import io
|
|
56
|
|
|
58
|
|
|
57
|
try:
|
|
59
|
try:
|
|
58
|
import httplib
|
|
60
|
import httplib
|
|
59
|
httplib.HTTPException
|
|
61
|
httplib.HTTPException
|
|
60
|
except ImportError:
|
|
62
|
except ImportError:
|
|
61
|
import http.client as httplib
|
|
63
|
import http.client as httplib
|
|
62
|
|
|
64
|
|
|
63
|
from . import (
|
|
65
|
from . import (
|
|
64
|
_readers,
|
|
66
|
_readers,
|
|
65
|
socketutil,
|
|
|
|
|
66
|
)
|
|
67
|
)
|
|
67
|
|
|
68
|
|
|
68
|
logger = logging.getLogger(__name__)
|
|
69
|
logger = logging.getLogger(__name__)
|
|
69
|
|
|
70
|
|
|
70
|
__all__ = ['HTTPConnection', 'HTTPResponse']
|
|
71
|
__all__ = ['HTTPConnection', 'HTTPResponse']
|
|
71
|
|
|
72
|
|
|
72
|
HTTP_VER_1_0 = 'HTTP/1.0'
|
|
73
|
HTTP_VER_1_0 = b'HTTP/1.0'
|
|
73
|
HTTP_VER_1_1 = 'HTTP/1.1'
|
|
74
|
HTTP_VER_1_1 = b'HTTP/1.1'
|
|
74
|
|
|
75
|
|
|
75
|
OUTGOING_BUFFER_SIZE = 1 << 15
|
|
76
|
OUTGOING_BUFFER_SIZE = 1 << 15
|
|
76
|
INCOMING_BUFFER_SIZE = 1 << 20
|
|
77
|
INCOMING_BUFFER_SIZE = 1 << 20
|
|
77
|
|
|
78
|
|
|
78
|
HDR_ACCEPT_ENCODING = 'accept-encoding'
|
|
79
|
HDR_ACCEPT_ENCODING = 'accept-encoding'
|
|
79
|
HDR_CONNECTION_CTRL = 'connection'
|
|
80
|
HDR_CONNECTION_CTRL = 'connection'
|
|
80
|
HDR_CONTENT_LENGTH = 'content-length'
|
|
81
|
HDR_CONTENT_LENGTH = 'content-length'
|
|
81
|
HDR_XFER_ENCODING = 'transfer-encoding'
|
|
82
|
HDR_XFER_ENCODING = 'transfer-encoding'
|
|
82
|
|
|
83
|
|
|
83
|
XFER_ENCODING_CHUNKED = 'chunked'
|
|
84
|
XFER_ENCODING_CHUNKED = 'chunked'
|
|
84
|
|
|
85
|
|
|
85
|
CONNECTION_CLOSE = 'close'
|
|
86
|
CONNECTION_CLOSE = 'close'
|
|
86
|
|
|
87
|
|
|
87
|
EOL = '\r\n'
|
|
88
|
EOL = b'\r\n'
|
|
88
|
_END_HEADERS = EOL * 2
|
|
89
|
_END_HEADERS = EOL * 2
|
|
89
|
|
|
90
|
|
|
90
|
# Based on some searching around, 1 second seems like a reasonable
|
|
91
|
# Based on some searching around, 1 second seems like a reasonable
|
|
91
|
# default here.
|
|
92
|
# default here.
|
|
92
|
TIMEOUT_ASSUME_CONTINUE = 1
|
|
93
|
TIMEOUT_ASSUME_CONTINUE = 1
|
|
93
|
TIMEOUT_DEFAULT = None
|
|
94
|
TIMEOUT_DEFAULT = None
|
|
94
|
|
|
95
|
|
|
|
|
|
96
|
if sys.version_info > (3, 0):
|
|
|
|
|
97
|
_unicode = str
|
|
|
|
|
98
|
else:
|
|
|
|
|
99
|
_unicode = unicode
|
|
|
|
|
100
|
|
|
|
|
|
101
|
def _ensurebytes(data):
|
|
|
|
|
102
|
if not isinstance(data, (_unicode, bytes)):
|
|
|
|
|
103
|
data = str(data)
|
|
|
|
|
104
|
if not isinstance(data, bytes):
|
|
|
|
|
105
|
try:
|
|
|
|
|
106
|
return data.encode('latin-1')
|
|
|
|
|
107
|
except UnicodeEncodeError as err:
|
|
|
|
|
108
|
raise UnicodeEncodeError(
|
|
|
|
|
109
|
err.encoding,
|
|
|
|
|
110
|
err.object,
|
|
|
|
|
111
|
err.start,
|
|
|
|
|
112
|
err.end,
|
|
|
|
|
113
|
'%r is not valid Latin-1 Use .encode("utf-8") '
|
|
|
|
|
114
|
'if sending as utf-8 is desired.' % (
|
|
|
|
|
115
|
data[err.start:err.end],))
|
|
|
|
|
116
|
return data
|
|
|
|
|
117
|
|
|
|
|
|
118
|
class _CompatMessage(email.message.Message):
|
|
|
|
|
119
|
"""Workaround for rfc822.Message and email.message.Message API diffs."""
|
|
|
|
|
120
|
|
|
|
|
|
121
|
@classmethod
|
|
|
|
|
122
|
def from_string(cls, s):
|
|
|
|
|
123
|
if sys.version_info > (3, 0):
|
|
|
|
|
124
|
# Python 3 can't decode headers from bytes, so we have to
|
|
|
|
|
125
|
# trust RFC 2616 and decode the headers as iso-8859-1
|
|
|
|
|
126
|
# bytes.
|
|
|
|
|
127
|
s = s.decode('iso-8859-1')
|
|
|
|
|
128
|
headers = email.message_from_string(s, _class=_CompatMessage)
|
|
|
|
|
129
|
# Fix multi-line headers to match httplib's behavior from
|
|
|
|
|
130
|
# Python 2.x, since email.message.Message handles them in
|
|
|
|
|
131
|
# slightly different ways.
|
|
|
|
|
132
|
if sys.version_info < (3, 0):
|
|
|
|
|
133
|
new = []
|
|
|
|
|
134
|
for h, v in headers._headers:
|
|
|
|
|
135
|
if '\r\n' in v:
|
|
|
|
|
136
|
v = '\n'.join([' ' + x.lstrip() for x in v.split('\r\n')])[1:]
|
|
|
|
|
137
|
new.append((h, v))
|
|
|
|
|
138
|
headers._headers = new
|
|
|
|
|
139
|
return headers
|
|
|
|
|
140
|
|
|
|
|
|
141
|
def getheaders(self, key):
|
|
|
|
|
142
|
return self.get_all(key)
|
|
|
|
|
143
|
|
|
|
|
|
144
|
def getheader(self, key, default=None):
|
|
|
|
|
145
|
return self.get(key, failobj=default)
|
|
|
|
|
146
|
|
|
95
|
|
|
147
|
|
|
96
|
class HTTPResponse(object):
|
|
148
|
class HTTPResponse(object):
|
|
97
|
"""Response from an HTTP server.
|
|
149
|
"""Response from an HTTP server.
|
|
98
|
|
|
150
|
|
|
99
|
The response will continue to load as available. If you need the
|
|
151
|
The response will continue to load as available. If you need the
|
|
100
|
complete response before continuing, check the .complete() method.
|
|
152
|
complete response before continuing, check the .complete() method.
|
|
101
|
"""
|
|
153
|
"""
|
|
102
|
def __init__(self, sock, timeout, method):
|
|
154
|
def __init__(self, sock, timeout, method):
|
|
103
|
self.sock = sock
|
|
155
|
self.sock = sock
|
|
104
|
self.method = method
|
|
156
|
self.method = method
|
|
105
|
self.raw_response = ''
|
|
157
|
self.raw_response = b''
|
|
106
|
self._headers_len = 0
|
|
158
|
self._headers_len = 0
|
|
107
|
self.headers = None
|
|
159
|
self.headers = None
|
|
108
|
self.will_close = False
|
|
160
|
self.will_close = False
|
|
109
|
self.status_line = ''
|
|
161
|
self.status_line = b''
|
|
110
|
self.status = None
|
|
162
|
self.status = None
|
|
111
|
self.continued = False
|
|
163
|
self.continued = False
|
|
112
|
self.http_version = None
|
|
164
|
self.http_version = None
|
|
113
|
self.reason = None
|
|
165
|
self.reason = None
|
|
114
|
self._reader = None
|
|
166
|
self._reader = None
|
|
115
|
|
|
167
|
|
|
116
|
self._read_location = 0
|
|
168
|
self._read_location = 0
|
|
117
|
self._eol = EOL
|
|
169
|
self._eol = EOL
|
|
118
|
|
|
170
|
|
|
119
|
self._timeout = timeout
|
|
171
|
self._timeout = timeout
|
|
120
|
|
|
172
|
|
|
121
|
@property
|
|
173
|
@property
|
|
122
|
def _end_headers(self):
|
|
174
|
def _end_headers(self):
|
|
123
|
return self._eol * 2
|
|
175
|
return self._eol * 2
|
|
124
|
|
|
176
|
|
|
125
|
def complete(self):
|
|
177
|
def complete(self):
|
|
126
|
"""Returns true if this response is completely loaded.
|
|
178
|
"""Returns true if this response is completely loaded.
|
|
127
|
|
|
179
|
|
|
128
|
Note that if this is a connection where complete means the
|
|
180
|
Note that if this is a connection where complete means the
|
|
129
|
socket is closed, this will nearly always return False, even
|
|
181
|
socket is closed, this will nearly always return False, even
|
|
130
|
in cases where all the data has actually been loaded.
|
|
182
|
in cases where all the data has actually been loaded.
|
|
131
|
"""
|
|
183
|
"""
|
|
132
|
if self._reader:
|
|
184
|
if self._reader:
|
|
133
|
return self._reader.done()
|
|
185
|
return self._reader.done()
|
|
134
|
|
|
186
|
|
|
135
|
def _close(self):
|
|
187
|
def _close(self):
|
|
136
|
if self._reader is not None:
|
|
188
|
if self._reader is not None:
|
|
137
|
# We're a friend of the reader class here.
|
|
189
|
# We're a friend of the reader class here.
|
|
138
|
# pylint: disable=W0212
|
|
190
|
# pylint: disable=W0212
|
|
139
|
self._reader._close()
|
|
191
|
self._reader._close()
|
|
140
|
|
|
192
|
|
|
141
|
def getheader(self, header, default=None):
|
|
193
|
def getheader(self, header, default=None):
|
|
142
|
return self.headers.getheader(header, default=default)
|
|
194
|
return self.headers.getheader(header, default=default)
|
|
143
|
|
|
195
|
|
|
144
|
def getheaders(self):
|
|
196
|
def getheaders(self):
|
|
|
|
|
197
|
if sys.version_info < (3, 0):
|
|
|
|
|
198
|
return [(k.lower(), v) for k, v in self.headers.items()]
|
|
|
|
|
199
|
# Starting in Python 3, headers aren't lowercased before being
|
|
|
|
|
200
|
# returned here.
|
|
145
|
return self.headers.items()
|
|
201
|
return self.headers.items()
|
|
146
|
|
|
202
|
|
|
147
|
def readline(self):
|
|
203
|
def readline(self):
|
|
148
|
"""Read a single line from the response body.
|
|
204
|
"""Read a single line from the response body.
|
|
149
|
|
|
205
|
|
|
150
|
This may block until either a line ending is found or the
|
|
206
|
This may block until either a line ending is found or the
|
|
151
|
response is complete.
|
|
207
|
response is complete.
|
|
152
|
"""
|
|
208
|
"""
|
|
153
|
blocks = []
|
|
209
|
blocks = []
|
|
154
|
while True:
|
|
210
|
while True:
|
|
155
|
self._reader.readto('\n', blocks)
|
|
211
|
self._reader.readto(b'\n', blocks)
|
|
156
|
|
|
212
|
|
|
157
|
if blocks and blocks[-1][-1] == '\n' or self.complete():
|
|
213
|
if blocks and blocks[-1][-1:] == b'\n' or self.complete():
|
|
158
|
break
|
|
214
|
break
|
|
159
|
|
|
215
|
|
|
160
|
self._select()
|
|
216
|
self._select()
|
|
161
|
|
|
217
|
|
|
162
|
return ''.join(blocks)
|
|
218
|
return b''.join(blocks)
|
|
163
|
|
|
219
|
|
|
164
|
def read(self, length=None):
|
|
220
|
def read(self, length=None):
|
|
165
|
"""Read data from the response body."""
|
|
221
|
"""Read data from the response body."""
|
|
166
|
# if length is None, unbounded read
|
|
222
|
# if length is None, unbounded read
|
|
167
|
while (not self.complete() # never select on a finished read
|
|
223
|
while (not self.complete() # never select on a finished read
|
|
168
|
and (not length # unbounded, so we wait for complete()
|
|
224
|
and (not length # unbounded, so we wait for complete()
|
|
169
|
or length > self._reader.available_data)):
|
|
225
|
or length > self._reader.available_data)):
|
|
170
|
self._select()
|
|
226
|
self._select()
|
|
171
|
if not length:
|
|
227
|
if not length:
|
|
172
|
length = self._reader.available_data
|
|
228
|
length = self._reader.available_data
|
|
173
|
r = self._reader.read(length)
|
|
229
|
r = self._reader.read(length)
|
|
174
|
if self.complete() and self.will_close:
|
|
230
|
if self.complete() and self.will_close:
|
|
175
|
self.sock.close()
|
|
231
|
self.sock.close()
|
|
176
|
return r
|
|
232
|
return r
|
|
177
|
|
|
233
|
|
|
178
|
def _select(self):
|
|
234
|
def _select(self):
|
|
179
|
r, unused_write, unused_err = select.select(
|
|
235
|
r, unused_write, unused_err = select.select(
|
|
180
|
[self.sock], [], [], self._timeout)
|
|
236
|
[self.sock], [], [], self._timeout)
|
|
181
|
if not r:
|
|
237
|
if not r:
|
|
182
|
# socket was not readable. If the response is not
|
|
238
|
# socket was not readable. If the response is not
|
|
183
|
# complete, raise a timeout.
|
|
239
|
# complete, raise a timeout.
|
|
184
|
if not self.complete():
|
|
240
|
if not self.complete():
|
|
185
|
logger.info('timed out with timeout of %s', self._timeout)
|
|
241
|
logger.info('timed out with timeout of %s', self._timeout)
|
|
186
|
raise HTTPTimeoutException('timeout reading data')
|
|
242
|
raise HTTPTimeoutException('timeout reading data')
|
|
187
|
try:
|
|
243
|
try:
|
|
188
|
data = self.sock.recv(INCOMING_BUFFER_SIZE)
|
|
244
|
data = self.sock.recv(INCOMING_BUFFER_SIZE)
|
|
189
|
except socket.sslerror as e:
|
|
245
|
except ssl.SSLError as e:
|
|
190
|
if e.args[0] != socket.SSL_ERROR_WANT_READ:
|
|
246
|
if e.args[0] != ssl.SSL_ERROR_WANT_READ:
|
|
191
|
raise
|
|
247
|
raise
|
|
192
|
logger.debug('SSL_ERROR_WANT_READ in _select, should retry later')
|
|
248
|
logger.debug('SSL_ERROR_WANT_READ in _select, should retry later')
|
|
193
|
return True
|
|
249
|
return True
|
|
194
|
logger.debug('response read %d data during _select', len(data))
|
|
250
|
logger.debug('response read %d data during _select', len(data))
|
|
195
|
# If the socket was readable and no data was read, that means
|
|
251
|
# If the socket was readable and no data was read, that means
|
|
196
|
# the socket was closed. Inform the reader (if any) so it can
|
|
252
|
# the socket was closed. Inform the reader (if any) so it can
|
|
197
|
# raise an exception if this is an invalid situation.
|
|
253
|
# raise an exception if this is an invalid situation.
|
|
198
|
if not data:
|
|
254
|
if not data:
|
|
199
|
if self._reader:
|
|
255
|
if self._reader:
|
|
200
|
# We're a friend of the reader class here.
|
|
256
|
# We're a friend of the reader class here.
|
|
201
|
# pylint: disable=W0212
|
|
257
|
# pylint: disable=W0212
|
|
202
|
self._reader._close()
|
|
258
|
self._reader._close()
|
|
203
|
return False
|
|
259
|
return False
|
|
204
|
else:
|
|
260
|
else:
|
|
205
|
self._load_response(data)
|
|
261
|
self._load_response(data)
|
|
206
|
return True
|
|
262
|
return True
|
|
207
|
|
|
263
|
|
|
208
|
# This method gets replaced by _load later, which confuses pylint.
|
|
264
|
# This method gets replaced by _load later, which confuses pylint.
|
|
209
|
def _load_response(self, data): # pylint: disable=E0202
|
|
265
|
def _load_response(self, data): # pylint: disable=E0202
|
|
210
|
# Being here implies we're not at the end of the headers yet,
|
|
266
|
# Being here implies we're not at the end of the headers yet,
|
|
211
|
# since at the end of this method if headers were completely
|
|
267
|
# since at the end of this method if headers were completely
|
|
212
|
# loaded we replace this method with the load() method of the
|
|
268
|
# loaded we replace this method with the load() method of the
|
|
213
|
# reader we created.
|
|
269
|
# reader we created.
|
|
214
|
self.raw_response += data
|
|
270
|
self.raw_response += data
|
|
215
|
# This is a bogus server with bad line endings
|
|
271
|
# This is a bogus server with bad line endings
|
|
216
|
if self._eol not in self.raw_response:
|
|
272
|
if self._eol not in self.raw_response:
|
|
217
|
for bad_eol in ('\n', '\r'):
|
|
273
|
for bad_eol in (b'\n', b'\r'):
|
|
218
|
if (bad_eol in self.raw_response
|
|
274
|
if (bad_eol in self.raw_response
|
|
219
|
# verify that bad_eol is not the end of the incoming data
|
|
275
|
# verify that bad_eol is not the end of the incoming data
|
|
220
|
# as this could be a response line that just got
|
|
276
|
# as this could be a response line that just got
|
|
221
|
# split between \r and \n.
|
|
277
|
# split between \r and \n.
|
|
222
|
and (self.raw_response.index(bad_eol) <
|
|
278
|
and (self.raw_response.index(bad_eol) <
|
|
223
|
(len(self.raw_response) - 1))):
|
|
279
|
(len(self.raw_response) - 1))):
|
|
224
|
logger.info('bogus line endings detected, '
|
|
280
|
logger.info('bogus line endings detected, '
|
|
225
|
'using %r for EOL', bad_eol)
|
|
281
|
'using %r for EOL', bad_eol)
|
|
226
|
self._eol = bad_eol
|
|
282
|
self._eol = bad_eol
|
|
227
|
break
|
|
283
|
break
|
|
228
|
# exit early if not at end of headers
|
|
284
|
# exit early if not at end of headers
|
|
229
|
if self._end_headers not in self.raw_response or self.headers:
|
|
285
|
if self._end_headers not in self.raw_response or self.headers:
|
|
230
|
return
|
|
286
|
return
|
|
231
|
|
|
287
|
|
|
232
|
# handle 100-continue response
|
|
288
|
# handle 100-continue response
|
|
233
|
hdrs, body = self.raw_response.split(self._end_headers, 1)
|
|
289
|
hdrs, body = self.raw_response.split(self._end_headers, 1)
|
|
234
|
unused_http_ver, status = hdrs.split(' ', 1)
|
|
290
|
unused_http_ver, status = hdrs.split(b' ', 1)
|
|
235
|
if status.startswith('100'):
|
|
291
|
if status.startswith(b'100'):
|
|
236
|
self.raw_response = body
|
|
292
|
self.raw_response = body
|
|
237
|
self.continued = True
|
|
293
|
self.continued = True
|
|
238
|
logger.debug('continue seen, setting body to %r', body)
|
|
294
|
logger.debug('continue seen, setting body to %r', body)
|
|
239
|
return
|
|
295
|
return
|
|
240
|
|
|
296
|
|
|
241
|
# arriving here means we should parse response headers
|
|
297
|
# arriving here means we should parse response headers
|
|
242
|
# as all headers have arrived completely
|
|
298
|
# as all headers have arrived completely
|
|
243
|
hdrs, body = self.raw_response.split(self._end_headers, 1)
|
|
299
|
hdrs, body = self.raw_response.split(self._end_headers, 1)
|
|
244
|
del self.raw_response
|
|
300
|
del self.raw_response
|
|
245
|
if self._eol in hdrs:
|
|
301
|
if self._eol in hdrs:
|
|
246
|
self.status_line, hdrs = hdrs.split(self._eol, 1)
|
|
302
|
self.status_line, hdrs = hdrs.split(self._eol, 1)
|
|
247
|
else:
|
|
303
|
else:
|
|
248
|
self.status_line = hdrs
|
|
304
|
self.status_line = hdrs
|
|
249
|
hdrs = ''
|
|
305
|
hdrs = b''
|
|
250
|
# TODO HTTP < 1.0 support
|
|
306
|
# TODO HTTP < 1.0 support
|
|
251
|
(self.http_version, self.status,
|
|
307
|
(self.http_version, self.status,
|
|
252
|
self.reason) = self.status_line.split(' ', 2)
|
|
308
|
self.reason) = self.status_line.split(b' ', 2)
|
|
253
|
self.status = int(self.status)
|
|
309
|
self.status = int(self.status)
|
|
254
|
if self._eol != EOL:
|
|
310
|
if self._eol != EOL:
|
|
255
|
hdrs = hdrs.replace(self._eol, '\r\n')
|
|
311
|
hdrs = hdrs.replace(self._eol, b'\r\n')
|
|
256
|
headers = rfc822.Message(io.StringIO(hdrs))
|
|
312
|
headers = _CompatMessage.from_string(hdrs)
|
|
257
|
content_len = None
|
|
313
|
content_len = None
|
|
258
|
if HDR_CONTENT_LENGTH in headers:
|
|
314
|
if HDR_CONTENT_LENGTH in headers:
|
|
259
|
content_len = int(headers[HDR_CONTENT_LENGTH])
|
|
315
|
content_len = int(headers[HDR_CONTENT_LENGTH])
|
|
260
|
if self.http_version == HTTP_VER_1_0:
|
|
316
|
if self.http_version == HTTP_VER_1_0:
|
|
261
|
self.will_close = True
|
|
317
|
self.will_close = True
|
|
262
|
elif HDR_CONNECTION_CTRL in headers:
|
|
318
|
elif HDR_CONNECTION_CTRL in headers:
|
|
263
|
self.will_close = (
|
|
319
|
self.will_close = (
|
|
264
|
headers[HDR_CONNECTION_CTRL].lower() == CONNECTION_CLOSE)
|
|
320
|
headers[HDR_CONNECTION_CTRL].lower() == CONNECTION_CLOSE)
|
|
265
|
if (HDR_XFER_ENCODING in headers
|
|
321
|
if (HDR_XFER_ENCODING in headers
|
|
266
|
and headers[HDR_XFER_ENCODING].lower() == XFER_ENCODING_CHUNKED):
|
|
322
|
and headers[HDR_XFER_ENCODING].lower() == XFER_ENCODING_CHUNKED):
|
|
267
|
self._reader = _readers.ChunkedReader(self._eol)
|
|
323
|
self._reader = _readers.ChunkedReader(self._eol)
|
|
268
|
logger.debug('using a chunked reader')
|
|
324
|
logger.debug('using a chunked reader')
|
|
269
|
else:
|
|
325
|
else:
|
|
270
|
# HEAD responses are forbidden from returning a body, and
|
|
326
|
# HEAD responses are forbidden from returning a body, and
|
|
271
|
# it's implausible for a CONNECT response to use
|
|
327
|
# it's implausible for a CONNECT response to use
|
|
272
|
# close-is-end logic for an OK response.
|
|
328
|
# close-is-end logic for an OK response.
|
|
273
|
if (self.method == 'HEAD' or
|
|
329
|
if (self.method == b'HEAD' or
|
|
274
|
(self.method == 'CONNECT' and content_len is None)):
|
|
330
|
(self.method == b'CONNECT' and content_len is None)):
|
|
275
|
content_len = 0
|
|
331
|
content_len = 0
|
|
276
|
if content_len is not None:
|
|
332
|
if content_len is not None:
|
|
277
|
logger.debug('using a content-length reader with length %d',
|
|
333
|
logger.debug('using a content-length reader with length %d',
|
|
278
|
content_len)
|
|
334
|
content_len)
|
|
279
|
self._reader = _readers.ContentLengthReader(content_len)
|
|
335
|
self._reader = _readers.ContentLengthReader(content_len)
|
|
280
|
else:
|
|
336
|
else:
|
|
281
|
# Response body had no length specified and is not
|
|
337
|
# Response body had no length specified and is not
|
|
282
|
# chunked, so the end of the body will only be
|
|
338
|
# chunked, so the end of the body will only be
|
|
283
|
# identifiable by the termination of the socket by the
|
|
339
|
# identifiable by the termination of the socket by the
|
|
284
|
# server. My interpretation of the spec means that we
|
|
340
|
# server. My interpretation of the spec means that we
|
|
285
|
# are correct in hitting this case if
|
|
341
|
# are correct in hitting this case if
|
|
286
|
# transfer-encoding, content-length, and
|
|
342
|
# transfer-encoding, content-length, and
|
|
287
|
# connection-control were left unspecified.
|
|
343
|
# connection-control were left unspecified.
|
|
288
|
self._reader = _readers.CloseIsEndReader()
|
|
344
|
self._reader = _readers.CloseIsEndReader()
|
|
289
|
logger.debug('using a close-is-end reader')
|
|
345
|
logger.debug('using a close-is-end reader')
|
|
290
|
self.will_close = True
|
|
346
|
self.will_close = True
|
|
291
|
|
|
347
|
|
|
292
|
if body:
|
|
348
|
if body:
|
|
293
|
# We're a friend of the reader class here.
|
|
349
|
# We're a friend of the reader class here.
|
|
294
|
# pylint: disable=W0212
|
|
350
|
# pylint: disable=W0212
|
|
295
|
self._reader._load(body)
|
|
351
|
self._reader._load(body)
|
|
296
|
logger.debug('headers complete')
|
|
352
|
logger.debug('headers complete')
|
|
297
|
self.headers = headers
|
|
353
|
self.headers = headers
|
|
298
|
# We're a friend of the reader class here.
|
|
354
|
# We're a friend of the reader class here.
|
|
299
|
# pylint: disable=W0212
|
|
355
|
# pylint: disable=W0212
|
|
300
|
self._load_response = self._reader._load
|
|
356
|
self._load_response = self._reader._load
|
|
301
|
|
|
357
|
|
|
302
|
def _foldheaders(headers):
|
|
358
|
def _foldheaders(headers):
|
|
303
|
"""Given some headers, rework them so we can safely overwrite values.
|
|
359
|
"""Given some headers, rework them so we can safely overwrite values.
|
|
304
|
|
|
360
|
|
|
305
|
>>> _foldheaders({'Accept-Encoding': 'wat'})
|
|
361
|
>>> _foldheaders({'Accept-Encoding': 'wat'})
|
|
306
|
{'accept-encoding': ('Accept-Encoding', 'wat')}
|
|
362
|
{'accept-encoding': ('Accept-Encoding', 'wat')}
|
|
307
|
"""
|
|
363
|
"""
|
|
308
|
return dict((k.lower(), (k, v)) for k, v in headers.iteritems())
|
|
364
|
return dict((k.lower(), (k, v)) for k, v in headers.items())
|
|
309
|
|
|
365
|
|
|
310
|
try:
|
|
366
|
try:
|
|
311
|
inspect.signature
|
|
367
|
inspect.signature
|
|
312
|
def _handlesarg(func, arg):
|
|
368
|
def _handlesarg(func, arg):
|
|
313
|
""" Try to determine if func accepts arg
|
|
369
|
""" Try to determine if func accepts arg
|
|
314
|
|
|
370
|
|
|
315
|
If it takes arg, return True
|
|
371
|
If it takes arg, return True
|
|
316
|
If it happens to take **args, then it could do anything:
|
|
372
|
If it happens to take **args, then it could do anything:
|
|
317
|
* It could throw a different TypeError, just for fun
|
|
373
|
* It could throw a different TypeError, just for fun
|
|
318
|
* It could throw an ArgumentError or anything else
|
|
374
|
* It could throw an ArgumentError or anything else
|
|
319
|
* It could choose not to throw an Exception at all
|
|
375
|
* It could choose not to throw an Exception at all
|
|
320
|
... return 'unknown'
|
|
376
|
... return 'unknown'
|
|
321
|
|
|
377
|
|
|
322
|
Otherwise, return False
|
|
378
|
Otherwise, return False
|
|
323
|
"""
|
|
379
|
"""
|
|
324
|
params = inspect.signature(func).parameters
|
|
380
|
params = inspect.signature(func).parameters
|
|
325
|
if arg in params:
|
|
381
|
if arg in params:
|
|
326
|
return True
|
|
382
|
return True
|
|
327
|
for p in params:
|
|
383
|
for p in params:
|
|
328
|
if params[p].kind == inspect._ParameterKind.VAR_KEYWORD:
|
|
384
|
if params[p].kind == inspect._ParameterKind.VAR_KEYWORD:
|
|
329
|
return 'unknown'
|
|
385
|
return 'unknown'
|
|
330
|
return False
|
|
386
|
return False
|
|
331
|
except AttributeError:
|
|
387
|
except AttributeError:
|
|
332
|
def _handlesarg(func, arg):
|
|
388
|
def _handlesarg(func, arg):
|
|
333
|
""" Try to determine if func accepts arg
|
|
389
|
""" Try to determine if func accepts arg
|
|
334
|
|
|
390
|
|
|
335
|
If it takes arg, return True
|
|
391
|
If it takes arg, return True
|
|
336
|
If it happens to take **args, then it could do anything:
|
|
392
|
If it happens to take **args, then it could do anything:
|
|
337
|
* It could throw a different TypeError, just for fun
|
|
393
|
* It could throw a different TypeError, just for fun
|
|
338
|
* It could throw an ArgumentError or anything else
|
|
394
|
* It could throw an ArgumentError or anything else
|
|
339
|
* It could choose not to throw an Exception at all
|
|
395
|
* It could choose not to throw an Exception at all
|
|
340
|
... return 'unknown'
|
|
396
|
... return 'unknown'
|
|
341
|
|
|
397
|
|
|
342
|
Otherwise, return False
|
|
398
|
Otherwise, return False
|
|
343
|
"""
|
|
399
|
"""
|
|
344
|
spec = inspect.getargspec(func)
|
|
400
|
spec = inspect.getargspec(func)
|
|
345
|
if arg in spec.args:
|
|
401
|
if arg in spec.args:
|
|
346
|
return True
|
|
402
|
return True
|
|
347
|
if spec.keywords:
|
|
403
|
if spec.keywords:
|
|
348
|
return 'unknown'
|
|
404
|
return 'unknown'
|
|
349
|
return False
|
|
405
|
return False
|
|
350
|
|
|
406
|
|
|
351
|
class HTTPConnection(object):
|
|
407
|
class HTTPConnection(object):
|
|
352
|
"""Connection to a single http server.
|
|
408
|
"""Connection to a single http server.
|
|
353
|
|
|
409
|
|
|
354
|
Supports 100-continue and keepalives natively. Uses select() for
|
|
410
|
Supports 100-continue and keepalives natively. Uses select() for
|
|
355
|
non-blocking socket operations.
|
|
411
|
non-blocking socket operations.
|
|
356
|
"""
|
|
412
|
"""
|
|
357
|
http_version = HTTP_VER_1_1
|
|
413
|
http_version = HTTP_VER_1_1
|
|
358
|
response_class = HTTPResponse
|
|
414
|
response_class = HTTPResponse
|
|
359
|
|
|
415
|
|
|
360
|
def __init__(self, host, port=None, use_ssl=None, ssl_validator=None,
|
|
416
|
def __init__(self, host, port=None, use_ssl=None, ssl_validator=None,
|
|
361
|
timeout=TIMEOUT_DEFAULT,
|
|
417
|
timeout=TIMEOUT_DEFAULT,
|
|
362
|
continue_timeout=TIMEOUT_ASSUME_CONTINUE,
|
|
418
|
continue_timeout=TIMEOUT_ASSUME_CONTINUE,
|
|
363
|
proxy_hostport=None, proxy_headers=None,
|
|
419
|
proxy_hostport=None, proxy_headers=None,
|
|
364
|
ssl_wrap_socket=None, **ssl_opts):
|
|
420
|
ssl_wrap_socket=None, **ssl_opts):
|
|
365
|
"""Create a new HTTPConnection.
|
|
421
|
"""Create a new HTTPConnection.
|
|
366
|
|
|
422
|
|
|
367
|
Args:
|
|
423
|
Args:
|
|
368
|
host: The host to which we'll connect.
|
|
424
|
host: The host to which we'll connect.
|
|
369
|
port: Optional. The port over which we'll connect. Default 80 for
|
|
425
|
port: Optional. The port over which we'll connect. Default 80 for
|
|
370
|
non-ssl, 443 for ssl.
|
|
426
|
non-ssl, 443 for ssl.
|
|
371
|
use_ssl: Optional. Whether to use ssl. Defaults to False if port is
|
|
427
|
use_ssl: Optional. Whether to use ssl. Defaults to False if port is
|
|
372
|
not 443, true if port is 443.
|
|
428
|
not 443, true if port is 443.
|
|
373
|
ssl_validator: a function(socket) to validate the ssl cert
|
|
429
|
ssl_validator: a function(socket) to validate the ssl cert
|
|
374
|
timeout: Optional. Connection timeout, default is TIMEOUT_DEFAULT.
|
|
430
|
timeout: Optional. Connection timeout, default is TIMEOUT_DEFAULT.
|
|
375
|
continue_timeout: Optional. Timeout for waiting on an expected
|
|
431
|
continue_timeout: Optional. Timeout for waiting on an expected
|
|
376
|
"100 Continue" response. Default is TIMEOUT_ASSUME_CONTINUE.
|
|
432
|
"100 Continue" response. Default is TIMEOUT_ASSUME_CONTINUE.
|
|
377
|
proxy_hostport: Optional. Tuple of (host, port) to use as an http
|
|
433
|
proxy_hostport: Optional. Tuple of (host, port) to use as an http
|
|
378
|
proxy for the connection. Default is to not use a proxy.
|
|
434
|
proxy for the connection. Default is to not use a proxy.
|
|
379
|
proxy_headers: Optional dict of header keys and values to send to
|
|
435
|
proxy_headers: Optional dict of header keys and values to send to
|
|
380
|
a proxy when using CONNECT. For compatibility with
|
|
436
|
a proxy when using CONNECT. For compatibility with
|
|
381
|
httplib, the Proxy-Authorization header may be
|
|
437
|
httplib, the Proxy-Authorization header may be
|
|
382
|
specified in headers for request(), which will clobber
|
|
438
|
specified in headers for request(), which will clobber
|
|
383
|
any such header specified here if specified. Providing
|
|
439
|
any such header specified here if specified. Providing
|
|
384
|
this option and not proxy_hostport will raise an
|
|
440
|
this option and not proxy_hostport will raise an
|
|
385
|
ValueError.
|
|
441
|
ValueError.
|
|
386
|
ssl_wrap_socket: Optional function to use for wrapping
|
|
442
|
ssl_wrap_socket: Optional function to use for wrapping
|
|
387
|
sockets. If unspecified, the one from the ssl module will
|
|
443
|
sockets. If unspecified, the one from the ssl module will
|
|
388
|
be used if available, or something that's compatible with
|
|
444
|
be used if available, or something that's compatible with
|
|
389
|
it if on a Python older than 2.6.
|
|
445
|
it if on a Python older than 2.6.
|
|
390
|
|
|
446
|
|
|
391
|
Any extra keyword arguments to this function will be provided
|
|
447
|
Any extra keyword arguments to this function will be provided
|
|
392
|
to the ssl_wrap_socket method. If no ssl
|
|
448
|
to the ssl_wrap_socket method. If no ssl
|
|
393
|
"""
|
|
449
|
"""
|
|
394
|
if port is None and host.count(':') == 1 or ']:' in host:
|
|
450
|
host = _ensurebytes(host)
|
|
395
|
host, port = host.rsplit(':', 1)
|
|
451
|
if port is None and host.count(b':') == 1 or b']:' in host:
|
|
|
|
|
452
|
host, port = host.rsplit(b':', 1)
|
|
396
|
port = int(port)
|
|
453
|
port = int(port)
|
|
397
|
if '[' in host:
|
|
454
|
if b'[' in host:
|
|
398
|
host = host[1:-1]
|
|
455
|
host = host[1:-1]
|
|
399
|
if ssl_wrap_socket is not None:
|
|
456
|
if ssl_wrap_socket is not None:
|
|
400
|
_wrap_socket = ssl_wrap_socket
|
|
457
|
_wrap_socket = ssl_wrap_socket
|
|
401
|
else:
|
|
458
|
else:
|
|
402
|
_wrap_socket = socketutil.wrap_socket
|
|
459
|
_wrap_socket = ssl.wrap_socket
|
|
403
|
call_wrap_socket = None
|
|
460
|
call_wrap_socket = None
|
|
404
|
handlesubar = _handlesarg(_wrap_socket, 'server_hostname')
|
|
461
|
handlesubar = _handlesarg(_wrap_socket, 'server_hostname')
|
|
405
|
if handlesubar is True:
|
|
462
|
if handlesubar is True:
|
|
406
|
# supports server_hostname
|
|
463
|
# supports server_hostname
|
|
407
|
call_wrap_socket = _wrap_socket
|
|
464
|
call_wrap_socket = _wrap_socket
|
|
408
|
handlesnobar = _handlesarg(_wrap_socket, 'serverhostname')
|
|
465
|
handlesnobar = _handlesarg(_wrap_socket, 'serverhostname')
|
|
409
|
if handlesnobar is True and handlesubar is not True:
|
|
466
|
if handlesnobar is True and handlesubar is not True:
|
|
410
|
# supports serverhostname
|
|
467
|
# supports serverhostname
|
|
411
|
def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
|
|
468
|
def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
|
|
412
|
return _wrap_socket(sock, serverhostname=server_hostname,
|
|
469
|
return _wrap_socket(sock, serverhostname=server_hostname,
|
|
413
|
**ssl_opts)
|
|
470
|
**ssl_opts)
|
|
414
|
if handlesubar is False and handlesnobar is False:
|
|
471
|
if handlesubar is False and handlesnobar is False:
|
|
415
|
# does not support either
|
|
472
|
# does not support either
|
|
416
|
def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
|
|
473
|
def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
|
|
417
|
return _wrap_socket(sock, **ssl_opts)
|
|
474
|
return _wrap_socket(sock, **ssl_opts)
|
|
418
|
if call_wrap_socket is None:
|
|
475
|
if call_wrap_socket is None:
|
|
419
|
# we assume it takes **args
|
|
476
|
# we assume it takes **args
|
|
420
|
def call_wrap_socket(sock, **ssl_opts):
|
|
477
|
def call_wrap_socket(sock, **ssl_opts):
|
|
421
|
if 'server_hostname' in ssl_opts:
|
|
478
|
if 'server_hostname' in ssl_opts:
|
|
422
|
ssl_opts['serverhostname'] = ssl_opts['server_hostname']
|
|
479
|
ssl_opts['serverhostname'] = ssl_opts['server_hostname']
|
|
423
|
return _wrap_socket(sock, **ssl_opts)
|
|
480
|
return _wrap_socket(sock, **ssl_opts)
|
|
424
|
self._ssl_wrap_socket = call_wrap_socket
|
|
481
|
self._ssl_wrap_socket = call_wrap_socket
|
|
425
|
if use_ssl is None and port is None:
|
|
482
|
if use_ssl is None and port is None:
|
|
426
|
use_ssl = False
|
|
483
|
use_ssl = False
|
|
427
|
port = 80
|
|
484
|
port = 80
|
|
428
|
elif use_ssl is None:
|
|
485
|
elif use_ssl is None:
|
|
429
|
use_ssl = (port == 443)
|
|
486
|
use_ssl = (port == 443)
|
|
430
|
elif port is None:
|
|
487
|
elif port is None:
|
|
431
|
port = (use_ssl and 443 or 80)
|
|
488
|
port = (use_ssl and 443 or 80)
|
|
432
|
self.port = port
|
|
489
|
self.port = port
|
|
433
|
if use_ssl and not socketutil.have_ssl:
|
|
|
|
|
434
|
raise Exception('ssl requested but unavailable on this Python')
|
|
|
|
|
435
|
self.ssl = use_ssl
|
|
490
|
self.ssl = use_ssl
|
|
436
|
self.ssl_opts = ssl_opts
|
|
491
|
self.ssl_opts = ssl_opts
|
|
437
|
self._ssl_validator = ssl_validator
|
|
492
|
self._ssl_validator = ssl_validator
|
|
438
|
self.host = host
|
|
493
|
self.host = host
|
|
439
|
self.sock = None
|
|
494
|
self.sock = None
|
|
440
|
self._current_response = None
|
|
495
|
self._current_response = None
|
|
441
|
self._current_response_taken = False
|
|
496
|
self._current_response_taken = False
|
|
442
|
if proxy_hostport is None:
|
|
497
|
if proxy_hostport is None:
|
|
443
|
self._proxy_host = self._proxy_port = None
|
|
498
|
self._proxy_host = self._proxy_port = None
|
|
444
|
if proxy_headers:
|
|
499
|
if proxy_headers:
|
|
445
|
raise ValueError(
|
|
500
|
raise ValueError(
|
|
446
|
'proxy_headers may not be specified unless '
|
|
501
|
'proxy_headers may not be specified unless '
|
|
447
|
'proxy_hostport is also specified.')
|
|
502
|
'proxy_hostport is also specified.')
|
|
448
|
else:
|
|
503
|
else:
|
|
449
|
self._proxy_headers = {}
|
|
504
|
self._proxy_headers = {}
|
|
450
|
else:
|
|
505
|
else:
|
|
451
|
self._proxy_host, self._proxy_port = proxy_hostport
|
|
506
|
self._proxy_host, self._proxy_port = proxy_hostport
|
|
452
|
self._proxy_headers = _foldheaders(proxy_headers or {})
|
|
507
|
self._proxy_headers = _foldheaders(proxy_headers or {})
|
|
453
|
|
|
508
|
|
|
454
|
self.timeout = timeout
|
|
509
|
self.timeout = timeout
|
|
455
|
self.continue_timeout = continue_timeout
|
|
510
|
self.continue_timeout = continue_timeout
|
|
456
|
|
|
511
|
|
|
457
|
def _connect(self, proxy_headers):
|
|
512
|
def _connect(self, proxy_headers):
|
|
458
|
"""Connect to the host and port specified in __init__."""
|
|
513
|
"""Connect to the host and port specified in __init__."""
|
|
459
|
if self.sock:
|
|
514
|
if self.sock:
|
|
460
|
return
|
|
515
|
return
|
|
461
|
if self._proxy_host is not None:
|
|
516
|
if self._proxy_host is not None:
|
|
462
|
logger.info('Connecting to http proxy %s:%s',
|
|
517
|
logger.info('Connecting to http proxy %s:%s',
|
|
463
|
self._proxy_host, self._proxy_port)
|
|
518
|
self._proxy_host, self._proxy_port)
|
|
464
|
sock = socketutil.create_connection((self._proxy_host,
|
|
519
|
sock = socket.create_connection((self._proxy_host,
|
|
465
|
self._proxy_port))
|
|
520
|
self._proxy_port))
|
|
466
|
if self.ssl:
|
|
521
|
if self.ssl:
|
|
467
|
data = self._buildheaders('CONNECT', '%s:%d' % (self.host,
|
|
522
|
data = self._buildheaders(b'CONNECT', b'%s:%d' % (self.host,
|
|
468
|
self.port),
|
|
523
|
self.port),
|
|
469
|
proxy_headers, HTTP_VER_1_0)
|
|
524
|
proxy_headers, HTTP_VER_1_0)
|
|
470
|
sock.send(data)
|
|
525
|
sock.send(data)
|
|
471
|
sock.setblocking(0)
|
|
526
|
sock.setblocking(0)
|
|
472
|
r = self.response_class(sock, self.timeout, 'CONNECT')
|
|
527
|
r = self.response_class(sock, self.timeout, b'CONNECT')
|
|
473
|
timeout_exc = HTTPTimeoutException(
|
|
528
|
timeout_exc = HTTPTimeoutException(
|
|
474
|
'Timed out waiting for CONNECT response from proxy')
|
|
529
|
'Timed out waiting for CONNECT response from proxy')
|
|
475
|
while not r.complete():
|
|
530
|
while not r.complete():
|
|
476
|
try:
|
|
531
|
try:
|
|
477
|
# We're a friend of the response class, so let
|
|
532
|
# We're a friend of the response class, so let
|
|
478
|
# us use the private attribute.
|
|
533
|
# us use the private attribute.
|
|
479
|
# pylint: disable=W0212
|
|
534
|
# pylint: disable=W0212
|
|
480
|
if not r._select():
|
|
535
|
if not r._select():
|
|
481
|
if not r.complete():
|
|
536
|
if not r.complete():
|
|
482
|
raise timeout_exc
|
|
537
|
raise timeout_exc
|
|
483
|
except HTTPTimeoutException:
|
|
538
|
except HTTPTimeoutException:
|
|
484
|
# This raise/except pattern looks goofy, but
|
|
539
|
# This raise/except pattern looks goofy, but
|
|
485
|
# _select can raise the timeout as well as the
|
|
540
|
# _select can raise the timeout as well as the
|
|
486
|
# loop body. I wish it wasn't this convoluted,
|
|
541
|
# loop body. I wish it wasn't this convoluted,
|
|
487
|
# but I don't have a better solution
|
|
542
|
# but I don't have a better solution
|
|
488
|
# immediately handy.
|
|
543
|
# immediately handy.
|
|
489
|
raise timeout_exc
|
|
544
|
raise timeout_exc
|
|
490
|
if r.status != 200:
|
|
545
|
if r.status != 200:
|
|
491
|
raise HTTPProxyConnectFailedException(
|
|
546
|
raise HTTPProxyConnectFailedException(
|
|
492
|
'Proxy connection failed: %d %s' % (r.status,
|
|
547
|
'Proxy connection failed: %d %s' % (r.status,
|
|
493
|
r.read()))
|
|
548
|
r.read()))
|
|
494
|
logger.info('CONNECT (for SSL) to %s:%s via proxy succeeded.',
|
|
549
|
logger.info('CONNECT (for SSL) to %s:%s via proxy succeeded.',
|
|
495
|
self.host, self.port)
|
|
550
|
self.host, self.port)
|
|
496
|
else:
|
|
551
|
else:
|
|
497
|
sock = socketutil.create_connection((self.host, self.port))
|
|
552
|
sock = socket.create_connection((self.host, self.port))
|
|
498
|
if self.ssl:
|
|
553
|
if self.ssl:
|
|
499
|
# This is the default, but in the case of proxied SSL
|
|
554
|
# This is the default, but in the case of proxied SSL
|
|
500
|
# requests the proxy logic above will have cleared
|
|
555
|
# requests the proxy logic above will have cleared
|
|
501
|
# blocking mode, so re-enable it just to be safe.
|
|
556
|
# blocking mode, so re-enable it just to be safe.
|
|
502
|
sock.setblocking(1)
|
|
557
|
sock.setblocking(1)
|
|
503
|
logger.debug('wrapping socket for ssl with options %r',
|
|
558
|
logger.debug('wrapping socket for ssl with options %r',
|
|
504
|
self.ssl_opts)
|
|
559
|
self.ssl_opts)
|
|
505
|
sock = self._ssl_wrap_socket(sock, server_hostname=self.host,
|
|
560
|
sock = self._ssl_wrap_socket(sock, server_hostname=self.host,
|
|
506
|
**self.ssl_opts)
|
|
561
|
**self.ssl_opts)
|
|
507
|
if self._ssl_validator:
|
|
562
|
if self._ssl_validator:
|
|
508
|
self._ssl_validator(sock)
|
|
563
|
self._ssl_validator(sock)
|
|
509
|
sock.setblocking(0)
|
|
564
|
sock.setblocking(0)
|
|
510
|
self.sock = sock
|
|
565
|
self.sock = sock
|
|
511
|
|
|
566
|
|
|
512
|
def _buildheaders(self, method, path, headers, http_ver):
|
|
567
|
def _buildheaders(self, method, path, headers, http_ver):
|
|
513
|
if self.ssl and self.port == 443 or self.port == 80:
|
|
568
|
if self.ssl and self.port == 443 or self.port == 80:
|
|
514
|
# default port for protocol, so leave it out
|
|
569
|
# default port for protocol, so leave it out
|
|
515
|
hdrhost = self.host
|
|
570
|
hdrhost = self.host
|
|
516
|
else:
|
|
571
|
else:
|
|
517
|
# include nonstandard port in header
|
|
572
|
# include nonstandard port in header
|
|
518
|
if ':' in self.host: # must be IPv6
|
|
573
|
if b':' in self.host: # must be IPv6
|
|
519
|
hdrhost = '[%s]:%d' % (self.host, self.port)
|
|
574
|
hdrhost = b'[%s]:%d' % (self.host, self.port)
|
|
520
|
else:
|
|
575
|
else:
|
|
521
|
hdrhost = '%s:%d' % (self.host, self.port)
|
|
576
|
hdrhost = b'%s:%d' % (self.host, self.port)
|
|
522
|
if self._proxy_host and not self.ssl:
|
|
577
|
if self._proxy_host and not self.ssl:
|
|
523
|
# When talking to a regular http proxy we must send the
|
|
578
|
# When talking to a regular http proxy we must send the
|
|
524
|
# full URI, but in all other cases we must not (although
|
|
579
|
# full URI, but in all other cases we must not (although
|
|
525
|
# technically RFC 2616 says servers must accept our
|
|
580
|
# technically RFC 2616 says servers must accept our
|
|
526
|
# request if we screw up, experimentally few do that
|
|
581
|
# request if we screw up, experimentally few do that
|
|
527
|
# correctly.)
|
|
582
|
# correctly.)
|
|
528
|
assert path[0] == '/', 'path must start with a /'
|
|
583
|
assert path[0:1] == b'/', 'path must start with a /'
|
|
529
|
path = 'http://%s%s' % (hdrhost, path)
|
|
584
|
path = b'http://%s%s' % (hdrhost, path)
|
|
530
|
outgoing = ['%s %s %s%s' % (method, path, http_ver, EOL)]
|
|
585
|
outgoing = [b'%s %s %s%s' % (method, path, http_ver, EOL)]
|
|
531
|
headers['host'] = ('Host', hdrhost)
|
|
586
|
headers[b'host'] = (b'Host', hdrhost)
|
|
532
|
headers[HDR_ACCEPT_ENCODING] = (HDR_ACCEPT_ENCODING, 'identity')
|
|
587
|
headers[HDR_ACCEPT_ENCODING] = (HDR_ACCEPT_ENCODING, 'identity')
|
|
533
|
for hdr, val in headers.itervalues():
|
|
588
|
for hdr, val in sorted((_ensurebytes(h), _ensurebytes(v))
|
|
534
|
outgoing.append('%s: %s%s' % (hdr, val, EOL))
|
|
589
|
for h, v in headers.values()):
|
|
|
|
|
590
|
outgoing.append(b'%s: %s%s' % (hdr, val, EOL))
|
|
535
|
outgoing.append(EOL)
|
|
591
|
outgoing.append(EOL)
|
|
536
|
return ''.join(outgoing)
|
|
592
|
return b''.join(outgoing)
|
|
537
|
|
|
593
|
|
|
538
|
def close(self):
|
|
594
|
def close(self):
|
|
539
|
"""Close the connection to the server.
|
|
595
|
"""Close the connection to the server.
|
|
540
|
|
|
596
|
|
|
541
|
This is a no-op if the connection is already closed. The
|
|
597
|
This is a no-op if the connection is already closed. The
|
|
542
|
connection may automatically close if requested by the server
|
|
598
|
connection may automatically close if requested by the server
|
|
543
|
or required by the nature of a response.
|
|
599
|
or required by the nature of a response.
|
|
544
|
"""
|
|
600
|
"""
|
|
545
|
if self.sock is None:
|
|
601
|
if self.sock is None:
|
|
546
|
return
|
|
602
|
return
|
|
547
|
self.sock.close()
|
|
603
|
self.sock.close()
|
|
548
|
self.sock = None
|
|
604
|
self.sock = None
|
|
549
|
logger.info('closed connection to %s on %s', self.host, self.port)
|
|
605
|
logger.info('closed connection to %s on %s', self.host, self.port)
|
|
550
|
|
|
606
|
|
|
551
|
def busy(self):
|
|
607
|
def busy(self):
|
|
552
|
"""Returns True if this connection object is currently in use.
|
|
608
|
"""Returns True if this connection object is currently in use.
|
|
553
|
|
|
609
|
|
|
554
|
If a response is still pending, this will return True, even if
|
|
610
|
If a response is still pending, this will return True, even if
|
|
555
|
the request has finished sending. In the future,
|
|
611
|
the request has finished sending. In the future,
|
|
556
|
HTTPConnection may transparently juggle multiple connections
|
|
612
|
HTTPConnection may transparently juggle multiple connections
|
|
557
|
to the server, in which case this will be useful to detect if
|
|
613
|
to the server, in which case this will be useful to detect if
|
|
558
|
any of those connections is ready for use.
|
|
614
|
any of those connections is ready for use.
|
|
559
|
"""
|
|
615
|
"""
|
|
560
|
cr = self._current_response
|
|
616
|
cr = self._current_response
|
|
561
|
if cr is not None:
|
|
617
|
if cr is not None:
|
|
562
|
if self._current_response_taken:
|
|
618
|
if self._current_response_taken:
|
|
563
|
if cr.will_close:
|
|
619
|
if cr.will_close:
|
|
564
|
self.sock = None
|
|
620
|
self.sock = None
|
|
565
|
self._current_response = None
|
|
621
|
self._current_response = None
|
|
566
|
return False
|
|
622
|
return False
|
|
567
|
elif cr.complete():
|
|
623
|
elif cr.complete():
|
|
568
|
self._current_response = None
|
|
624
|
self._current_response = None
|
|
569
|
return False
|
|
625
|
return False
|
|
570
|
return True
|
|
626
|
return True
|
|
571
|
return False
|
|
627
|
return False
|
|
572
|
|
|
628
|
|
|
573
|
def _reconnect(self, where, pheaders):
|
|
629
|
def _reconnect(self, where, pheaders):
|
|
574
|
logger.info('reconnecting during %s', where)
|
|
630
|
logger.info('reconnecting during %s', where)
|
|
575
|
self.close()
|
|
631
|
self.close()
|
|
576
|
self._connect(pheaders)
|
|
632
|
self._connect(pheaders)
|
|
577
|
|
|
633
|
|
|
578
|
def request(self, method, path, body=None, headers={},
|
|
634
|
def request(self, method, path, body=None, headers={},
|
|
579
|
expect_continue=False):
|
|
635
|
expect_continue=False):
|
|
580
|
"""Send a request to the server.
|
|
636
|
"""Send a request to the server.
|
|
581
|
|
|
637
|
|
|
582
|
For increased flexibility, this does not return the response
|
|
638
|
For increased flexibility, this does not return the response
|
|
583
|
object. Future versions of HTTPConnection that juggle multiple
|
|
639
|
object. Future versions of HTTPConnection that juggle multiple
|
|
584
|
sockets will be able to send (for example) 5 requests all at
|
|
640
|
sockets will be able to send (for example) 5 requests all at
|
|
585
|
once, and then let the requests arrive as data is
|
|
641
|
once, and then let the requests arrive as data is
|
|
586
|
available. Use the `getresponse()` method to retrieve the
|
|
642
|
available. Use the `getresponse()` method to retrieve the
|
|
587
|
response.
|
|
643
|
response.
|
|
588
|
"""
|
|
644
|
"""
|
|
|
|
|
645
|
method = _ensurebytes(method)
|
|
|
|
|
646
|
path = _ensurebytes(path)
|
|
589
|
if self.busy():
|
|
647
|
if self.busy():
|
|
590
|
raise httplib.CannotSendRequest(
|
|
648
|
raise httplib.CannotSendRequest(
|
|
591
|
'Can not send another request before '
|
|
649
|
'Can not send another request before '
|
|
592
|
'current response is read!')
|
|
650
|
'current response is read!')
|
|
593
|
self._current_response_taken = False
|
|
651
|
self._current_response_taken = False
|
|
594
|
|
|
652
|
|
|
595
|
logger.info('sending %s request for %s to %s on port %s',
|
|
653
|
logger.info('sending %s request for %s to %s on port %s',
|
|
596
|
method, path, self.host, self.port)
|
|
654
|
method, path, self.host, self.port)
|
|
|
|
|
655
|
|
|
597
|
hdrs = _foldheaders(headers)
|
|
656
|
hdrs = _foldheaders(headers)
|
|
598
|
if hdrs.get('expect', ('', ''))[1].lower() == '100-continue':
|
|
657
|
# Figure out headers that have to be computed from the request
|
|
|
|
|
658
|
# body.
|
|
|
|
|
659
|
chunked = False
|
|
|
|
|
660
|
if body and HDR_CONTENT_LENGTH not in hdrs:
|
|
|
|
|
661
|
if getattr(body, '__len__', False):
|
|
|
|
|
662
|
hdrs[HDR_CONTENT_LENGTH] = (HDR_CONTENT_LENGTH,
|
|
|
|
|
663
|
b'%d' % len(body))
|
|
|
|
|
664
|
elif getattr(body, 'read', False):
|
|
|
|
|
665
|
hdrs[HDR_XFER_ENCODING] = (HDR_XFER_ENCODING,
|
|
|
|
|
666
|
XFER_ENCODING_CHUNKED)
|
|
|
|
|
667
|
chunked = True
|
|
|
|
|
668
|
else:
|
|
|
|
|
669
|
raise BadRequestData('body has no __len__() nor read()')
|
|
|
|
|
670
|
# Figure out expect-continue header
|
|
|
|
|
671
|
if hdrs.get('expect', ('', ''))[1].lower() == b'100-continue':
|
|
599
|
expect_continue = True
|
|
672
|
expect_continue = True
|
|
600
|
elif expect_continue:
|
|
673
|
elif expect_continue:
|
|
601
|
hdrs['expect'] = ('Expect', '100-Continue')
|
|
674
|
hdrs['expect'] = (b'Expect', b'100-Continue')
|
|
602
|
# httplib compatibility: if the user specified a
|
|
675
|
# httplib compatibility: if the user specified a
|
|
603
|
# proxy-authorization header, that's actually intended for a
|
|
676
|
# proxy-authorization header, that's actually intended for a
|
|
604
|
# proxy CONNECT action, not the real request, but only if
|
|
677
|
# proxy CONNECT action, not the real request, but only if
|
|
605
|
# we're going to use a proxy.
|
|
678
|
# we're going to use a proxy.
|
|
606
|
pheaders = dict(self._proxy_headers)
|
|
679
|
pheaders = dict(self._proxy_headers)
|
|
607
|
if self._proxy_host and self.ssl:
|
|
680
|
if self._proxy_host and self.ssl:
|
|
608
|
pa = hdrs.pop('proxy-authorization', None)
|
|
681
|
pa = hdrs.pop('proxy-authorization', None)
|
|
609
|
if pa is not None:
|
|
682
|
if pa is not None:
|
|
610
|
pheaders['proxy-authorization'] = pa
|
|
683
|
pheaders['proxy-authorization'] = pa
|
|
611
|
|
|
684
|
# Build header data
|
|
612
|
chunked = False
|
|
685
|
outgoing_headers = self._buildheaders(
|
|
613
|
if body and HDR_CONTENT_LENGTH not in hdrs:
|
|
686
|
method, path, hdrs, self.http_version)
|
|
614
|
if getattr(body, '__len__', False):
|
|
|
|
|
615
|
hdrs[HDR_CONTENT_LENGTH] = (HDR_CONTENT_LENGTH, len(body))
|
|
|
|
|
616
|
elif getattr(body, 'read', False):
|
|
|
|
|
617
|
hdrs[HDR_XFER_ENCODING] = (HDR_XFER_ENCODING,
|
|
|
|
|
618
|
XFER_ENCODING_CHUNKED)
|
|
|
|
|
619
|
chunked = True
|
|
|
|
|
620
|
else:
|
|
|
|
|
621
|
raise BadRequestData('body has no __len__() nor read()')
|
|
|
|
|
622
|
|
|
687
|
|
|
623
|
# If we're reusing the underlying socket, there are some
|
|
688
|
# If we're reusing the underlying socket, there are some
|
|
624
|
# conditions where we'll want to retry, so make a note of the
|
|
689
|
# conditions where we'll want to retry, so make a note of the
|
|
625
|
# state of self.sock
|
|
690
|
# state of self.sock
|
|
626
|
fresh_socket = self.sock is None
|
|
691
|
fresh_socket = self.sock is None
|
|
627
|
self._connect(pheaders)
|
|
692
|
self._connect(pheaders)
|
|
628
|
outgoing_headers = self._buildheaders(
|
|
|
|
|
629
|
method, path, hdrs, self.http_version)
|
|
|
|
|
630
|
response = None
|
|
693
|
response = None
|
|
631
|
first = True
|
|
694
|
first = True
|
|
632
|
|
|
695
|
|
|
633
|
while ((outgoing_headers or body)
|
|
696
|
while ((outgoing_headers or body)
|
|
634
|
and not (response and response.complete())):
|
|
697
|
and not (response and response.complete())):
|
|
635
|
select_timeout = self.timeout
|
|
698
|
select_timeout = self.timeout
|
|
636
|
out = outgoing_headers or body
|
|
699
|
out = outgoing_headers or body
|
|
637
|
blocking_on_continue = False
|
|
700
|
blocking_on_continue = False
|
|
638
|
if expect_continue and not outgoing_headers and not (
|
|
701
|
if expect_continue and not outgoing_headers and not (
|
|
639
|
response and (response.headers or response.continued)):
|
|
702
|
response and (response.headers or response.continued)):
|
|
640
|
logger.info(
|
|
703
|
logger.info(
|
|
641
|
'waiting up to %s seconds for'
|
|
704
|
'waiting up to %s seconds for'
|
|
642
|
' continue response from server',
|
|
705
|
' continue response from server',
|
|
643
|
self.continue_timeout)
|
|
706
|
self.continue_timeout)
|
|
644
|
select_timeout = self.continue_timeout
|
|
707
|
select_timeout = self.continue_timeout
|
|
645
|
blocking_on_continue = True
|
|
708
|
blocking_on_continue = True
|
|
646
|
out = False
|
|
709
|
out = False
|
|
647
|
if out:
|
|
710
|
if out:
|
|
648
|
w = [self.sock]
|
|
711
|
w = [self.sock]
|
|
649
|
else:
|
|
712
|
else:
|
|
650
|
w = []
|
|
713
|
w = []
|
|
651
|
r, w, x = select.select([self.sock], w, [], select_timeout)
|
|
714
|
r, w, x = select.select([self.sock], w, [], select_timeout)
|
|
652
|
# if we were expecting a 100 continue and it's been long
|
|
715
|
# if we were expecting a 100 continue and it's been long
|
|
653
|
# enough, just go ahead and assume it's ok. This is the
|
|
716
|
# enough, just go ahead and assume it's ok. This is the
|
|
654
|
# recommended behavior from the RFC.
|
|
717
|
# recommended behavior from the RFC.
|
|
655
|
if r == w == x == []:
|
|
718
|
if r == w == x == []:
|
|
656
|
if blocking_on_continue:
|
|
719
|
if blocking_on_continue:
|
|
657
|
expect_continue = False
|
|
720
|
expect_continue = False
|
|
658
|
logger.info('no response to continue expectation from '
|
|
721
|
logger.info('no response to continue expectation from '
|
|
659
|
'server, optimistically sending request body')
|
|
722
|
'server, optimistically sending request body')
|
|
660
|
else:
|
|
723
|
else:
|
|
661
|
raise HTTPTimeoutException('timeout sending data')
|
|
724
|
raise HTTPTimeoutException('timeout sending data')
|
|
662
|
was_first = first
|
|
725
|
was_first = first
|
|
663
|
|
|
726
|
|
|
664
|
# incoming data
|
|
727
|
# incoming data
|
|
665
|
if r:
|
|
728
|
if r:
|
|
666
|
try:
|
|
729
|
try:
|
|
667
|
try:
|
|
730
|
try:
|
|
668
|
data = r[0].recv(INCOMING_BUFFER_SIZE)
|
|
731
|
data = r[0].recv(INCOMING_BUFFER_SIZE)
|
|
669
|
except socket.sslerror as e:
|
|
732
|
except ssl.SSLError as e:
|
|
670
|
if e.args[0] != socket.SSL_ERROR_WANT_READ:
|
|
733
|
if e.args[0] != ssl.SSL_ERROR_WANT_READ:
|
|
671
|
raise
|
|
734
|
raise
|
|
672
|
logger.debug('SSL_ERROR_WANT_READ while sending '
|
|
735
|
logger.debug('SSL_ERROR_WANT_READ while sending '
|
|
673
|
'data, retrying...')
|
|
736
|
'data, retrying...')
|
|
674
|
continue
|
|
737
|
continue
|
|
675
|
if not data:
|
|
738
|
if not data:
|
|
676
|
logger.info('socket appears closed in read')
|
|
739
|
logger.info('socket appears closed in read')
|
|
677
|
self.sock = None
|
|
740
|
self.sock = None
|
|
678
|
self._current_response = None
|
|
741
|
self._current_response = None
|
|
679
|
if response is not None:
|
|
742
|
if response is not None:
|
|
680
|
# We're a friend of the response class, so let
|
|
743
|
# We're a friend of the response class, so let
|
|
681
|
# us use the private attribute.
|
|
744
|
# us use the private attribute.
|
|
682
|
# pylint: disable=W0212
|
|
745
|
# pylint: disable=W0212
|
|
683
|
response._close()
|
|
746
|
response._close()
|
|
684
|
# This if/elif ladder is a bit subtle,
|
|
747
|
# This if/elif ladder is a bit subtle,
|
|
685
|
# comments in each branch should help.
|
|
748
|
# comments in each branch should help.
|
|
686
|
if response is not None and response.complete():
|
|
749
|
if response is not None and response.complete():
|
|
687
|
# Server responded completely and then
|
|
750
|
# Server responded completely and then
|
|
688
|
# closed the socket. We should just shut
|
|
751
|
# closed the socket. We should just shut
|
|
689
|
# things down and let the caller get their
|
|
752
|
# things down and let the caller get their
|
|
690
|
# response.
|
|
753
|
# response.
|
|
691
|
logger.info('Got an early response, '
|
|
754
|
logger.info('Got an early response, '
|
|
692
|
'aborting remaining request.')
|
|
755
|
'aborting remaining request.')
|
|
693
|
break
|
|
756
|
break
|
|
694
|
elif was_first and response is None:
|
|
757
|
elif was_first and response is None:
|
|
695
|
# Most likely a keepalive that got killed
|
|
758
|
# Most likely a keepalive that got killed
|
|
696
|
# on the server's end. Commonly happens
|
|
759
|
# on the server's end. Commonly happens
|
|
697
|
# after getting a really large response
|
|
760
|
# after getting a really large response
|
|
698
|
# from the server.
|
|
761
|
# from the server.
|
|
699
|
logger.info(
|
|
762
|
logger.info(
|
|
700
|
'Connection appeared closed in read on first'
|
|
763
|
'Connection appeared closed in read on first'
|
|
701
|
' request loop iteration, will retry.')
|
|
764
|
' request loop iteration, will retry.')
|
|
702
|
self._reconnect('read', pheaders)
|
|
765
|
self._reconnect('read', pheaders)
|
|
703
|
continue
|
|
766
|
continue
|
|
704
|
else:
|
|
767
|
else:
|
|
705
|
# We didn't just send the first data hunk,
|
|
768
|
# We didn't just send the first data hunk,
|
|
706
|
# and either have a partial response or no
|
|
769
|
# and either have a partial response or no
|
|
707
|
# response at all. There's really nothing
|
|
770
|
# response at all. There's really nothing
|
|
708
|
# meaningful we can do here.
|
|
771
|
# meaningful we can do here.
|
|
709
|
raise HTTPStateError(
|
|
772
|
raise HTTPStateError(
|
|
710
|
'Connection appears closed after '
|
|
773
|
'Connection appears closed after '
|
|
711
|
'some request data was written, but the '
|
|
774
|
'some request data was written, but the '
|
|
712
|
'response was missing or incomplete!')
|
|
775
|
'response was missing or incomplete!')
|
|
713
|
logger.debug('read %d bytes in request()', len(data))
|
|
776
|
logger.debug('read %d bytes in request()', len(data))
|
|
714
|
if response is None:
|
|
777
|
if response is None:
|
|
715
|
response = self.response_class(
|
|
778
|
response = self.response_class(
|
|
716
|
r[0], self.timeout, method)
|
|
779
|
r[0], self.timeout, method)
|
|
717
|
# We're a friend of the response class, so let us
|
|
780
|
# We're a friend of the response class, so let us
|
|
718
|
# use the private attribute.
|
|
781
|
# use the private attribute.
|
|
719
|
# pylint: disable=W0212
|
|
782
|
# pylint: disable=W0212
|
|
720
|
response._load_response(data)
|
|
783
|
response._load_response(data)
|
|
721
|
# Jump to the next select() call so we load more
|
|
784
|
# Jump to the next select() call so we load more
|
|
722
|
# data if the server is still sending us content.
|
|
785
|
# data if the server is still sending us content.
|
|
723
|
continue
|
|
786
|
continue
|
|
724
|
except socket.error as e:
|
|
787
|
except socket.error as e:
|
|
725
|
if e[0] != errno.EPIPE and not was_first:
|
|
788
|
if e[0] != errno.EPIPE and not was_first:
|
|
726
|
raise
|
|
789
|
raise
|
|
727
|
|
|
790
|
|
|
728
|
# outgoing data
|
|
791
|
# outgoing data
|
|
729
|
if w and out:
|
|
792
|
if w and out:
|
|
730
|
try:
|
|
793
|
try:
|
|
731
|
if getattr(out, 'read', False):
|
|
794
|
if getattr(out, 'read', False):
|
|
732
|
# pylint guesses the type of out incorrectly here
|
|
795
|
# pylint guesses the type of out incorrectly here
|
|
733
|
# pylint: disable=E1103
|
|
796
|
# pylint: disable=E1103
|
|
734
|
data = out.read(OUTGOING_BUFFER_SIZE)
|
|
797
|
data = out.read(OUTGOING_BUFFER_SIZE)
|
|
735
|
if not data:
|
|
798
|
if not data:
|
|
736
|
continue
|
|
799
|
continue
|
|
737
|
if len(data) < OUTGOING_BUFFER_SIZE:
|
|
800
|
if len(data) < OUTGOING_BUFFER_SIZE:
|
|
738
|
if chunked:
|
|
801
|
if chunked:
|
|
739
|
body = '0' + EOL + EOL
|
|
802
|
body = b'0' + EOL + EOL
|
|
740
|
else:
|
|
803
|
else:
|
|
741
|
body = None
|
|
804
|
body = None
|
|
742
|
if chunked:
|
|
805
|
if chunked:
|
|
743
|
out = hex(len(data))[2:] + EOL + data + EOL
|
|
806
|
# This encode is okay because we know
|
|
|
|
|
807
|
# hex() is building us only 0-9 and a-f
|
|
|
|
|
808
|
# digits.
|
|
|
|
|
809
|
asciilen = hex(len(data))[2:].encode('ascii')
|
|
|
|
|
810
|
out = asciilen + EOL + data + EOL
|
|
744
|
else:
|
|
811
|
else:
|
|
745
|
out = data
|
|
812
|
out = data
|
|
746
|
amt = w[0].send(out)
|
|
813
|
amt = w[0].send(out)
|
|
747
|
except socket.error as e:
|
|
814
|
except socket.error as e:
|
|
748
|
if e[0] == socket.SSL_ERROR_WANT_WRITE and self.ssl:
|
|
815
|
if e[0] == ssl.SSL_ERROR_WANT_WRITE and self.ssl:
|
|
749
|
# This means that SSL hasn't flushed its buffer into
|
|
816
|
# This means that SSL hasn't flushed its buffer into
|
|
750
|
# the socket yet.
|
|
817
|
# the socket yet.
|
|
751
|
# TODO: find a way to block on ssl flushing its buffer
|
|
818
|
# TODO: find a way to block on ssl flushing its buffer
|
|
752
|
# similar to selecting on a raw socket.
|
|
819
|
# similar to selecting on a raw socket.
|
|
753
|
continue
|
|
820
|
continue
|
|
754
|
if e[0] == errno.EWOULDBLOCK or e[0] == errno.EAGAIN:
|
|
821
|
if e[0] == errno.EWOULDBLOCK or e[0] == errno.EAGAIN:
|
|
755
|
continue
|
|
822
|
continue
|
|
756
|
elif (e[0] not in (errno.ECONNRESET, errno.EPIPE)
|
|
823
|
elif (e[0] not in (errno.ECONNRESET, errno.EPIPE)
|
|
757
|
and not first):
|
|
824
|
and not first):
|
|
758
|
raise
|
|
825
|
raise
|
|
759
|
self._reconnect('write', pheaders)
|
|
826
|
self._reconnect('write', pheaders)
|
|
760
|
amt = self.sock.send(out)
|
|
827
|
amt = self.sock.send(out)
|
|
761
|
logger.debug('sent %d', amt)
|
|
828
|
logger.debug('sent %d', amt)
|
|
762
|
first = False
|
|
829
|
first = False
|
|
763
|
if out is body:
|
|
830
|
if out is body:
|
|
764
|
body = out[amt:]
|
|
831
|
body = out[amt:]
|
|
765
|
else:
|
|
832
|
else:
|
|
766
|
outgoing_headers = out[amt:]
|
|
833
|
outgoing_headers = out[amt:]
|
|
|
|
|
834
|
# End of request-sending loop.
|
|
767
|
|
|
835
|
|
|
768
|
# close if the server response said to or responded before eating
|
|
836
|
# close if the server response said to or responded before eating
|
|
769
|
# the whole request
|
|
837
|
# the whole request
|
|
770
|
if response is None:
|
|
838
|
if response is None:
|
|
771
|
response = self.response_class(self.sock, self.timeout, method)
|
|
839
|
response = self.response_class(self.sock, self.timeout, method)
|
|
772
|
if not fresh_socket:
|
|
840
|
if not fresh_socket:
|
|
773
|
if not response._select():
|
|
841
|
if not response._select():
|
|
774
|
# This means the response failed to get any response
|
|
842
|
# This means the response failed to get any response
|
|
775
|
# data at all, and in all probability the socket was
|
|
843
|
# data at all, and in all probability the socket was
|
|
776
|
# closed before the server even saw our request. Try
|
|
844
|
# closed before the server even saw our request. Try
|
|
777
|
# the request again on a fresh socket.
|
|
845
|
# the request again on a fresh socket.
|
|
778
|
logger.debug('response._select() failed during request().'
|
|
846
|
logger.debug('response._select() failed during request().'
|
|
779
|
' Assuming request needs to be retried.')
|
|
847
|
' Assuming request needs to be retried.')
|
|
780
|
self.sock = None
|
|
848
|
self.sock = None
|
|
781
|
# Call this method explicitly to re-try the
|
|
849
|
# Call this method explicitly to re-try the
|
|
782
|
# request. We don't use self.request() because
|
|
850
|
# request. We don't use self.request() because
|
|
783
|
# some tools (notably Mercurial) expect to be able
|
|
851
|
# some tools (notably Mercurial) expect to be able
|
|
784
|
# to subclass and redefine request(), and they
|
|
852
|
# to subclass and redefine request(), and they
|
|
785
|
# don't have the same argspec as we do.
|
|
853
|
# don't have the same argspec as we do.
|
|
786
|
#
|
|
854
|
#
|
|
787
|
# TODO restructure sending of requests to avoid
|
|
855
|
# TODO restructure sending of requests to avoid
|
|
788
|
# this recursion
|
|
856
|
# this recursion
|
|
789
|
return HTTPConnection.request(
|
|
857
|
return HTTPConnection.request(
|
|
790
|
self, method, path, body=body, headers=headers,
|
|
858
|
self, method, path, body=body, headers=headers,
|
|
791
|
expect_continue=expect_continue)
|
|
859
|
expect_continue=expect_continue)
|
|
792
|
data_left = bool(outgoing_headers or body)
|
|
860
|
data_left = bool(outgoing_headers or body)
|
|
793
|
if data_left:
|
|
861
|
if data_left:
|
|
794
|
logger.info('stopped sending request early, '
|
|
862
|
logger.info('stopped sending request early, '
|
|
795
|
'will close the socket to be safe.')
|
|
863
|
'will close the socket to be safe.')
|
|
796
|
response.will_close = True
|
|
864
|
response.will_close = True
|
|
797
|
if response.will_close:
|
|
865
|
if response.will_close:
|
|
798
|
# The socket will be closed by the response, so we disown
|
|
866
|
# The socket will be closed by the response, so we disown
|
|
799
|
# the socket
|
|
867
|
# the socket
|
|
800
|
self.sock = None
|
|
868
|
self.sock = None
|
|
801
|
self._current_response = response
|
|
869
|
self._current_response = response
|
|
802
|
|
|
870
|
|
|
803
|
def getresponse(self):
|
|
871
|
def getresponse(self):
|
|
804
|
"""Returns the response to the most recent request."""
|
|
872
|
"""Returns the response to the most recent request."""
|
|
805
|
if self._current_response is None:
|
|
873
|
if self._current_response is None:
|
|
806
|
raise httplib.ResponseNotReady()
|
|
874
|
raise httplib.ResponseNotReady()
|
|
807
|
r = self._current_response
|
|
875
|
r = self._current_response
|
|
808
|
while r.headers is None:
|
|
876
|
while r.headers is None:
|
|
809
|
# We're a friend of the response class, so let us use the
|
|
877
|
# We're a friend of the response class, so let us use the
|
|
810
|
# private attribute.
|
|
878
|
# private attribute.
|
|
811
|
# pylint: disable=W0212
|
|
879
|
# pylint: disable=W0212
|
|
812
|
if not r._select() and not r.complete():
|
|
880
|
if not r._select() and not r.complete():
|
|
813
|
raise _readers.HTTPRemoteClosedError()
|
|
881
|
raise _readers.HTTPRemoteClosedError()
|
|
814
|
if r.will_close:
|
|
882
|
if r.will_close:
|
|
815
|
self.sock = None
|
|
883
|
self.sock = None
|
|
816
|
self._current_response = None
|
|
884
|
self._current_response = None
|
|
817
|
elif r.complete():
|
|
885
|
elif r.complete():
|
|
818
|
self._current_response = None
|
|
886
|
self._current_response = None
|
|
819
|
else:
|
|
887
|
else:
|
|
820
|
self._current_response_taken = True
|
|
888
|
self._current_response_taken = True
|
|
821
|
return r
|
|
889
|
return r
|
|
822
|
|
|
890
|
|
|
823
|
|
|
891
|
|
|
824
|
class HTTPTimeoutException(httplib.HTTPException):
|
|
892
|
class HTTPTimeoutException(httplib.HTTPException):
|
|
825
|
"""A timeout occurred while waiting on the server."""
|
|
893
|
"""A timeout occurred while waiting on the server."""
|
|
826
|
|
|
894
|
|
|
827
|
|
|
895
|
|
|
828
|
class BadRequestData(httplib.HTTPException):
|
|
896
|
class BadRequestData(httplib.HTTPException):
|
|
829
|
"""Request body object has neither __len__ nor read."""
|
|
897
|
"""Request body object has neither __len__ nor read."""
|
|
830
|
|
|
898
|
|
|
831
|
|
|
899
|
|
|
832
|
class HTTPProxyConnectFailedException(httplib.HTTPException):
|
|
900
|
class HTTPProxyConnectFailedException(httplib.HTTPException):
|
|
833
|
"""Connecting to the HTTP proxy failed."""
|
|
901
|
"""Connecting to the HTTP proxy failed."""
|
|
834
|
|
|
902
|
|
|
835
|
|
|
903
|
|
|
836
|
class HTTPStateError(httplib.HTTPException):
|
|
904
|
class HTTPStateError(httplib.HTTPException):
|
|
837
|
"""Invalid internal state encountered."""
|
|
905
|
"""Invalid internal state encountered."""
|
|
838
|
|
|
906
|
|
|
839
|
# Forward this exception type from _readers since it needs to be part
|
|
907
|
# Forward this exception type from _readers since it needs to be part
|
|
840
|
# of the public API.
|
|
908
|
# of the public API.
|
|
841
|
HTTPRemoteClosedError = _readers.HTTPRemoteClosedError
|
|
909
|
HTTPRemoteClosedError = _readers.HTTPRemoteClosedError
|
|
842
|
# no-check-code
|
|
910
|
# no-check-code
|