blob: 1fe358e0b947effd4bbc514958a3b6859d234afd [file] [log] [blame]
Greg Stein5e0fa402000-06-26 08:28:01 +00001"""HTTP/1.1 client library
Guido van Rossum41999c11997-12-09 00:12:23 +00002
Greg Stein5e0fa402000-06-26 08:28:01 +00003<intro stuff goes here>
4<other stuff, too>
Guido van Rossum41999c11997-12-09 00:12:23 +00005
Greg Stein5e0fa402000-06-26 08:28:01 +00006HTTPConnection go through a number of "states", which defines when a client
7may legally make another request or fetch the response for a particular
8request. This diagram details these state transitions:
Guido van Rossum41999c11997-12-09 00:12:23 +00009
Greg Stein5e0fa402000-06-26 08:28:01 +000010 (null)
11 |
12 | HTTPConnection()
13 v
14 Idle
15 |
16 | putrequest()
17 v
18 Request-started
19 |
20 | ( putheader() )* endheaders()
21 v
22 Request-sent
23 |
24 | response = getresponse()
25 v
26 Unread-response [Response-headers-read]
27 |\____________________
28 | \
29 | response.read() | putrequest()
30 v v
31 Idle Req-started-unread-response
32 _______/|
33 / |
34 response.read() | | ( putheader() )* endheaders()
35 v v
36 Request-started Req-sent-unread-response
37 |
38 | response.read()
39 v
40 Request-sent
41
42This diagram presents the following rules:
43 -- a second request may not be started until {response-headers-read}
44 -- a response [object] cannot be retrieved until {request-sent}
45 -- there is no differentiation between an unread response body and a
46 partially read response body
47
48Note: this enforcement is applied by the HTTPConnection class. The
49 HTTPResponse class does not enforce this state machine, which
50 implies sophisticated clients may accelerate the request/response
51 pipeline. Caution should be taken, though: accelerating the states
52 beyond the above pattern may imply knowledge of the server's
53 connection-close behavior for certain requests. For example, it
54 is impossible to tell whether the server will close the connection
55 UNTIL the response headers have been read; this means that further
56 requests cannot be placed into the pipeline until it is known that
57 the server will NOT be closing the connection.
58
59Logical State __state __response
60------------- ------- ----------
61Idle _CS_IDLE None
62Request-started _CS_REQ_STARTED None
63Request-sent _CS_REQ_SENT None
64Unread-response _CS_IDLE <response_class>
65Req-started-unread-response _CS_REQ_STARTED <response_class>
66Req-sent-unread-response _CS_REQ_SENT <response_class>
Guido van Rossum41999c11997-12-09 00:12:23 +000067"""
Guido van Rossum23acc951994-02-21 16:36:04 +000068
Guido van Rossum23acc951994-02-21 16:36:04 +000069import socket
70import string
Guido van Rossum65ab98c1995-08-07 20:13:02 +000071import mimetools
Guido van Rossum23acc951994-02-21 16:36:04 +000072
Guido van Rossum09c8b6c1999-12-07 21:37:17 +000073try:
Greg Steindd6eefb2000-07-18 09:09:48 +000074 from cStringIO import StringIO
Greg Stein5e0fa402000-06-26 08:28:01 +000075except ImportError:
Greg Steindd6eefb2000-07-18 09:09:48 +000076 from StringIO import StringIO
Guido van Rossum09c8b6c1999-12-07 21:37:17 +000077
Guido van Rossum23acc951994-02-21 16:36:04 +000078HTTP_PORT = 80
Guido van Rossum09c8b6c1999-12-07 21:37:17 +000079HTTPS_PORT = 443
80
Greg Stein5e0fa402000-06-26 08:28:01 +000081_UNKNOWN = 'UNKNOWN'
82
83# connection states
84_CS_IDLE = 'Idle'
85_CS_REQ_STARTED = 'Request-started'
86_CS_REQ_SENT = 'Request-sent'
87
88
89class HTTPResponse:
Greg Steindd6eefb2000-07-18 09:09:48 +000090 def __init__(self, sock):
91 self.fp = sock.makefile('rb', 0)
Greg Stein5e0fa402000-06-26 08:28:01 +000092
Greg Steindd6eefb2000-07-18 09:09:48 +000093 self.msg = None
Greg Stein5e0fa402000-06-26 08:28:01 +000094
Greg Steindd6eefb2000-07-18 09:09:48 +000095 # from the Status-Line of the response
96 self.version = _UNKNOWN # HTTP-Version
97 self.status = _UNKNOWN # Status-Code
98 self.reason = _UNKNOWN # Reason-Phrase
Greg Stein5e0fa402000-06-26 08:28:01 +000099
Greg Steindd6eefb2000-07-18 09:09:48 +0000100 self.chunked = _UNKNOWN # is "chunked" being used?
101 self.chunk_left = _UNKNOWN # bytes left to read in current chunk
102 self.length = _UNKNOWN # number of bytes left in response
103 self.will_close = _UNKNOWN # conn will close at end of response
Greg Stein5e0fa402000-06-26 08:28:01 +0000104
Greg Steindd6eefb2000-07-18 09:09:48 +0000105 def begin(self):
106 if self.msg is not None:
107 # we've already started reading the response
108 return
Greg Stein5e0fa402000-06-26 08:28:01 +0000109
Greg Stein5e0fa402000-06-26 08:28:01 +0000110 line = self.fp.readline()
Greg Steindd6eefb2000-07-18 09:09:48 +0000111 try:
112 [version, status, reason] = string.split(line, None, 2)
113 except ValueError:
114 try:
115 [version, status] = string.split(line, None, 1)
116 reason = ""
117 except ValueError:
118 self.close()
119 raise BadStatusLine(line)
120 if version[:5] != 'HTTP/':
121 self.close()
122 raise BadStatusLine(line)
Greg Stein5e0fa402000-06-26 08:28:01 +0000123
Greg Steindd6eefb2000-07-18 09:09:48 +0000124 self.status = status = int(status)
125 self.reason = string.strip(reason)
Greg Stein5e0fa402000-06-26 08:28:01 +0000126
Greg Steindd6eefb2000-07-18 09:09:48 +0000127 if version == 'HTTP/1.0':
128 self.version = 10
129 elif version[:7] == 'HTTP/1.':
130 self.version = 11 # use HTTP/1.1 code for HTTP/1.x where x>=1
131 else:
132 raise UnknownProtocol(version)
Greg Stein5e0fa402000-06-26 08:28:01 +0000133
Greg Steindd6eefb2000-07-18 09:09:48 +0000134 self.msg = mimetools.Message(self.fp, 0)
Greg Stein5e0fa402000-06-26 08:28:01 +0000135
Greg Steindd6eefb2000-07-18 09:09:48 +0000136 # don't let the msg keep an fp
137 self.msg.fp = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000138
Greg Steindd6eefb2000-07-18 09:09:48 +0000139 # are we using the chunked-style of transfer encoding?
140 tr_enc = self.msg.getheader('transfer-encoding')
141 if tr_enc:
142 if string.lower(tr_enc) != 'chunked':
143 raise UnknownTransferEncoding()
144 self.chunked = 1
145 self.chunk_left = None
146 else:
147 self.chunked = 0
Greg Stein5e0fa402000-06-26 08:28:01 +0000148
Greg Steindd6eefb2000-07-18 09:09:48 +0000149 # will the connection close at the end of the response?
150 conn = self.msg.getheader('connection')
151 if conn:
152 conn = string.lower(conn)
153 # a "Connection: close" will always close the connection. if we
154 # don't see that and this is not HTTP/1.1, then the connection will
155 # close unless we see a Keep-Alive header.
156 self.will_close = string.find(conn, 'close') != -1 or \
157 ( self.version != 11 and \
158 not self.msg.getheader('keep-alive') )
159 else:
160 # for HTTP/1.1, the connection will always remain open
161 # otherwise, it will remain open IFF we see a Keep-Alive header
162 self.will_close = self.version != 11 and \
163 not self.msg.getheader('keep-alive')
Greg Stein5e0fa402000-06-26 08:28:01 +0000164
Greg Steindd6eefb2000-07-18 09:09:48 +0000165 # do we have a Content-Length?
166 # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
167 length = self.msg.getheader('content-length')
168 if length and not self.chunked:
Jeremy Hylton30a81812000-09-14 20:34:27 +0000169 try:
170 self.length = int(length)
171 except ValueError:
172 self.length = None
Greg Steindd6eefb2000-07-18 09:09:48 +0000173 else:
174 self.length = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000175
Greg Steindd6eefb2000-07-18 09:09:48 +0000176 # does the body have a fixed length? (of zero)
177 if (status == 204 or # No Content
178 status == 304 or # Not Modified
179 100 <= status < 200): # 1xx codes
180 self.length = 0
Greg Stein5e0fa402000-06-26 08:28:01 +0000181
Greg Steindd6eefb2000-07-18 09:09:48 +0000182 # if the connection remains open, and we aren't using chunked, and
183 # a content-length was not provided, then assume that the connection
184 # WILL close.
185 if not self.will_close and \
186 not self.chunked and \
187 self.length is None:
188 self.will_close = 1
Greg Stein5e0fa402000-06-26 08:28:01 +0000189
Greg Steindd6eefb2000-07-18 09:09:48 +0000190 # if there is no body, then close NOW. read() may never be called, thus
191 # we will never mark self as closed.
192 if self.length == 0:
193 self.close()
Greg Stein5e0fa402000-06-26 08:28:01 +0000194
Greg Steindd6eefb2000-07-18 09:09:48 +0000195 def close(self):
196 if self.fp:
197 self.fp.close()
198 self.fp = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000199
Greg Steindd6eefb2000-07-18 09:09:48 +0000200 def isclosed(self):
201 # NOTE: it is possible that we will not ever call self.close(). This
202 # case occurs when will_close is TRUE, length is None, and we
203 # read up to the last byte, but NOT past it.
204 #
205 # IMPLIES: if will_close is FALSE, then self.close() will ALWAYS be
206 # called, meaning self.isclosed() is meaningful.
207 return self.fp is None
208
209 def read(self, amt=None):
210 if self.fp is None:
211 return ''
212
213 if self.chunked:
214 chunk_left = self.chunk_left
215 value = ''
216 while 1:
217 if chunk_left is None:
218 line = self.fp.readline()
219 i = string.find(line, ';')
220 if i >= 0:
221 line = line[:i] # strip chunk-extensions
222 chunk_left = string.atoi(line, 16)
223 if chunk_left == 0:
224 break
225 if amt is None:
226 value = value + self._safe_read(chunk_left)
227 elif amt < chunk_left:
228 value = value + self._safe_read(amt)
229 self.chunk_left = chunk_left - amt
230 return value
231 elif amt == chunk_left:
232 value = value + self._safe_read(amt)
233 self._safe_read(2) # toss the CRLF at the end of the chunk
234 self.chunk_left = None
235 return value
236 else:
237 value = value + self._safe_read(chunk_left)
238 amt = amt - chunk_left
239
240 # we read the whole chunk, get another
241 self._safe_read(2) # toss the CRLF at the end of the chunk
242 chunk_left = None
243
244 # read and discard trailer up to the CRLF terminator
245 ### note: we shouldn't have any trailers!
246 while 1:
247 line = self.fp.readline()
248 if line == '\r\n':
249 break
250
251 # we read everything; close the "file"
252 self.close()
253
254 return value
255
256 elif amt is None:
257 # unbounded read
258 if self.will_close:
259 s = self.fp.read()
260 else:
261 s = self._safe_read(self.length)
262 self.close() # we read everything
263 return s
264
265 if self.length is not None:
266 if amt > self.length:
267 # clip the read to the "end of response"
268 amt = self.length
269 self.length = self.length - amt
270
271 # we do not use _safe_read() here because this may be a .will_close
272 # connection, and the user is reading more bytes than will be provided
273 # (for example, reading in 1k chunks)
274 s = self.fp.read(amt)
275
276 # close our "file" if we know we should
277 ### I'm not sure about the len(s) < amt part; we should be safe because
278 ### we shouldn't be using non-blocking sockets
279 if self.length == 0 or len(s) < amt:
280 self.close()
281
282 return s
283
284 def _safe_read(self, amt):
285 """Read the number of bytes requested, compensating for partial reads.
286
287 Normally, we have a blocking socket, but a read() can be interrupted
288 by a signal (resulting in a partial read).
289
290 Note that we cannot distinguish between EOF and an interrupt when zero
291 bytes have been read. IncompleteRead() will be raised in this
292 situation.
293
294 This function should be used when <amt> bytes "should" be present for
295 reading. If the bytes are truly not available (due to EOF), then the
296 IncompleteRead exception can be used to detect the problem.
297 """
298 s = ''
299 while amt > 0:
300 chunk = self.fp.read(amt)
301 if not chunk:
302 raise IncompleteRead(s)
303 s = s + chunk
304 amt = amt - len(chunk)
305 return s
306
307 def getheader(self, name, default=None):
308 if self.msg is None:
309 raise ResponseNotReady()
310 return self.msg.getheader(name, default)
Greg Stein5e0fa402000-06-26 08:28:01 +0000311
312
313class HTTPConnection:
314
Greg Steindd6eefb2000-07-18 09:09:48 +0000315 _http_vsn = 11
316 _http_vsn_str = 'HTTP/1.1'
Greg Stein5e0fa402000-06-26 08:28:01 +0000317
Greg Steindd6eefb2000-07-18 09:09:48 +0000318 response_class = HTTPResponse
319 default_port = HTTP_PORT
320 auto_open = 1
Greg Stein5e0fa402000-06-26 08:28:01 +0000321
Greg Steindd6eefb2000-07-18 09:09:48 +0000322 def __init__(self, host, port=None):
323 self.sock = None
324 self.__response = None
325 self.__state = _CS_IDLE
Greg Stein5e0fa402000-06-26 08:28:01 +0000326
Greg Steindd6eefb2000-07-18 09:09:48 +0000327 self._set_hostport(host, port)
Greg Stein5e0fa402000-06-26 08:28:01 +0000328
Greg Steindd6eefb2000-07-18 09:09:48 +0000329 def _set_hostport(self, host, port):
330 if port is None:
331 i = string.find(host, ':')
332 if i >= 0:
333 port = int(host[i+1:])
334 host = host[:i]
335 else:
336 port = self.default_port
337 self.host = host
338 self.port = port
Greg Stein5e0fa402000-06-26 08:28:01 +0000339
Greg Steindd6eefb2000-07-18 09:09:48 +0000340 def connect(self):
341 """Connect to the host and port specified in __init__."""
342 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
343 self.sock.connect((self.host, self.port))
Greg Stein5e0fa402000-06-26 08:28:01 +0000344
Greg Steindd6eefb2000-07-18 09:09:48 +0000345 def close(self):
346 """Close the connection to the HTTP server."""
347 if self.sock:
348 self.sock.close() # close it manually... there may be other refs
349 self.sock = None
350 if self.__response:
351 self.__response.close()
352 self.__response = None
353 self.__state = _CS_IDLE
Greg Stein5e0fa402000-06-26 08:28:01 +0000354
Greg Steindd6eefb2000-07-18 09:09:48 +0000355 def send(self, str):
356 """Send `str' to the server."""
357 if self.sock is None:
358 if self.auto_open:
359 self.connect()
360 else:
361 raise NotConnected()
Greg Stein5e0fa402000-06-26 08:28:01 +0000362
Greg Steindd6eefb2000-07-18 09:09:48 +0000363 # send the data to the server. if we get a broken pipe, then close
364 # the socket. we want to reconnect when somebody tries to send again.
365 #
366 # NOTE: we DO propagate the error, though, because we cannot simply
367 # ignore the error... the caller will know if they can retry.
368 try:
369 self.sock.send(str)
370 except socket.error, v:
371 if v[0] == 32: # Broken pipe
372 self.close()
373 raise
Greg Stein5e0fa402000-06-26 08:28:01 +0000374
Greg Steindd6eefb2000-07-18 09:09:48 +0000375 def putrequest(self, method, url):
376 """Send a request to the server.
Greg Stein5e0fa402000-06-26 08:28:01 +0000377
Greg Steindd6eefb2000-07-18 09:09:48 +0000378 `method' specifies an HTTP request method, e.g. 'GET'.
379 `url' specifies the object being requested, e.g. '/index.html'.
380 """
Greg Stein5e0fa402000-06-26 08:28:01 +0000381
Greg Steindd6eefb2000-07-18 09:09:48 +0000382 # check if a prior response has been completed
383 if self.__response and self.__response.isclosed():
384 self.__response = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000385
Greg Steindd6eefb2000-07-18 09:09:48 +0000386 #
387 # in certain cases, we cannot issue another request on this connection.
388 # this occurs when:
389 # 1) we are in the process of sending a request. (_CS_REQ_STARTED)
390 # 2) a response to a previous request has signalled that it is going
391 # to close the connection upon completion.
392 # 3) the headers for the previous response have not been read, thus
393 # we cannot determine whether point (2) is true. (_CS_REQ_SENT)
394 #
395 # if there is no prior response, then we can request at will.
396 #
397 # if point (2) is true, then we will have passed the socket to the
398 # response (effectively meaning, "there is no prior response"), and
399 # will open a new one when a new request is made.
400 #
401 # Note: if a prior response exists, then we *can* start a new request.
402 # We are not allowed to begin fetching the response to this new
403 # request, however, until that prior response is complete.
404 #
405 if self.__state == _CS_IDLE:
406 self.__state = _CS_REQ_STARTED
407 else:
408 raise CannotSendRequest()
Greg Stein5e0fa402000-06-26 08:28:01 +0000409
Greg Steindd6eefb2000-07-18 09:09:48 +0000410 if not url:
411 url = '/'
412 str = '%s %s %s\r\n' % (method, url, self._http_vsn_str)
Greg Stein5e0fa402000-06-26 08:28:01 +0000413
Greg Steindd6eefb2000-07-18 09:09:48 +0000414 try:
415 self.send(str)
416 except socket.error, v:
417 # trap 'Broken pipe' if we're allowed to automatically reconnect
418 if v[0] != 32 or not self.auto_open:
419 raise
420 # try one more time (the socket was closed; this will reopen)
421 self.send(str)
Greg Stein5e0fa402000-06-26 08:28:01 +0000422
Greg Steindd6eefb2000-07-18 09:09:48 +0000423 if self._http_vsn == 11:
424 # Issue some standard headers for better HTTP/1.1 compliance
Greg Stein5e0fa402000-06-26 08:28:01 +0000425
Greg Steindd6eefb2000-07-18 09:09:48 +0000426 # this header is issued *only* for HTTP/1.1 connections. more
427 # specifically, this means it is only issued when the client uses
428 # the new HTTPConnection() class. backwards-compat clients will
429 # be using HTTP/1.0 and those clients may be issuing this header
430 # themselves. we should NOT issue it twice; some web servers (such
431 # as Apache) barf when they see two Host: headers
432 self.putheader('Host', self.host)
Greg Stein5e0fa402000-06-26 08:28:01 +0000433
Greg Steindd6eefb2000-07-18 09:09:48 +0000434 # note: we are assuming that clients will not attempt to set these
435 # headers since *this* library must deal with the
436 # consequences. this also means that when the supporting
437 # libraries are updated to recognize other forms, then this
438 # code should be changed (removed or updated).
Greg Stein5e0fa402000-06-26 08:28:01 +0000439
Greg Steindd6eefb2000-07-18 09:09:48 +0000440 # we only want a Content-Encoding of "identity" since we don't
441 # support encodings such as x-gzip or x-deflate.
442 self.putheader('Accept-Encoding', 'identity')
Greg Stein5e0fa402000-06-26 08:28:01 +0000443
Greg Steindd6eefb2000-07-18 09:09:48 +0000444 # we can accept "chunked" Transfer-Encodings, but no others
445 # NOTE: no TE header implies *only* "chunked"
446 #self.putheader('TE', 'chunked')
Greg Stein5e0fa402000-06-26 08:28:01 +0000447
Greg Steindd6eefb2000-07-18 09:09:48 +0000448 # if TE is supplied in the header, then it must appear in a
449 # Connection header.
450 #self.putheader('Connection', 'TE')
Greg Stein5e0fa402000-06-26 08:28:01 +0000451
Greg Steindd6eefb2000-07-18 09:09:48 +0000452 else:
453 # For HTTP/1.0, the server will assume "not chunked"
454 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000455
Greg Steindd6eefb2000-07-18 09:09:48 +0000456 def putheader(self, header, value):
457 """Send a request header line to the server.
Greg Stein5e0fa402000-06-26 08:28:01 +0000458
Greg Steindd6eefb2000-07-18 09:09:48 +0000459 For example: h.putheader('Accept', 'text/html')
460 """
461 if self.__state != _CS_REQ_STARTED:
462 raise CannotSendHeader()
Greg Stein5e0fa402000-06-26 08:28:01 +0000463
Greg Steindd6eefb2000-07-18 09:09:48 +0000464 str = '%s: %s\r\n' % (header, value)
465 self.send(str)
Greg Stein5e0fa402000-06-26 08:28:01 +0000466
Greg Steindd6eefb2000-07-18 09:09:48 +0000467 def endheaders(self):
468 """Indicate that the last header line has been sent to the server."""
Greg Stein5e0fa402000-06-26 08:28:01 +0000469
Greg Steindd6eefb2000-07-18 09:09:48 +0000470 if self.__state == _CS_REQ_STARTED:
471 self.__state = _CS_REQ_SENT
472 else:
473 raise CannotSendHeader()
Greg Stein5e0fa402000-06-26 08:28:01 +0000474
Greg Steindd6eefb2000-07-18 09:09:48 +0000475 self.send('\r\n')
Greg Stein5e0fa402000-06-26 08:28:01 +0000476
Greg Steindd6eefb2000-07-18 09:09:48 +0000477 def request(self, method, url, body=None, headers={}):
478 """Send a complete request to the server."""
Greg Stein5e0fa402000-06-26 08:28:01 +0000479
Greg Steindd6eefb2000-07-18 09:09:48 +0000480 try:
481 self._send_request(method, url, body, headers)
482 except socket.error, v:
483 # trap 'Broken pipe' if we're allowed to automatically reconnect
484 if v[0] != 32 or not self.auto_open:
485 raise
486 # try one more time
487 self._send_request(method, url, body, headers)
Greg Stein5e0fa402000-06-26 08:28:01 +0000488
Greg Steindd6eefb2000-07-18 09:09:48 +0000489 def _send_request(self, method, url, body, headers):
490 self.putrequest(method, url)
Greg Stein5e0fa402000-06-26 08:28:01 +0000491
Greg Steindd6eefb2000-07-18 09:09:48 +0000492 if body:
493 self.putheader('Content-Length', str(len(body)))
494 for hdr, value in headers.items():
495 self.putheader(hdr, value)
496 self.endheaders()
Greg Stein5e0fa402000-06-26 08:28:01 +0000497
Greg Steindd6eefb2000-07-18 09:09:48 +0000498 if body:
499 self.send(body)
Greg Stein5e0fa402000-06-26 08:28:01 +0000500
Greg Steindd6eefb2000-07-18 09:09:48 +0000501 def getresponse(self):
502 "Get the response from the server."
Greg Stein5e0fa402000-06-26 08:28:01 +0000503
Greg Steindd6eefb2000-07-18 09:09:48 +0000504 # check if a prior response has been completed
505 if self.__response and self.__response.isclosed():
506 self.__response = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000507
Greg Steindd6eefb2000-07-18 09:09:48 +0000508 #
509 # if a prior response exists, then it must be completed (otherwise, we
510 # cannot read this response's header to determine the connection-close
511 # behavior)
512 #
513 # note: if a prior response existed, but was connection-close, then the
514 # socket and response were made independent of this HTTPConnection
515 # object since a new request requires that we open a whole new
516 # connection
517 #
518 # this means the prior response had one of two states:
519 # 1) will_close: this connection was reset and the prior socket and
520 # response operate independently
521 # 2) persistent: the response was retained and we await its
522 # isclosed() status to become true.
523 #
524 if self.__state != _CS_REQ_SENT or self.__response:
525 raise ResponseNotReady()
Greg Stein5e0fa402000-06-26 08:28:01 +0000526
Greg Steindd6eefb2000-07-18 09:09:48 +0000527 response = self.response_class(self.sock)
Greg Stein5e0fa402000-06-26 08:28:01 +0000528
Greg Steindd6eefb2000-07-18 09:09:48 +0000529 response.begin()
530 self.__state = _CS_IDLE
Greg Stein5e0fa402000-06-26 08:28:01 +0000531
Greg Steindd6eefb2000-07-18 09:09:48 +0000532 if response.will_close:
533 # this effectively passes the connection to the response
534 self.close()
535 else:
536 # remember this, so we can tell when it is complete
537 self.__response = response
Greg Stein5e0fa402000-06-26 08:28:01 +0000538
Greg Steindd6eefb2000-07-18 09:09:48 +0000539 return response
Greg Stein5e0fa402000-06-26 08:28:01 +0000540
541
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000542class FakeSocket:
Greg Steindd6eefb2000-07-18 09:09:48 +0000543 def __init__(self, sock, ssl):
544 self.__sock = sock
545 self.__ssl = ssl
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000546
Jeremy Hylton4d746fc2000-08-23 20:34:17 +0000547 def makefile(self, mode, bufsize=None):
548 """Return a readable file-like object with data from socket.
549
550 This method offers only partial support for the makefile
551 interface of a real socket. It only supports modes 'r' and
552 'rb' and the bufsize argument is ignored.
553
554 The returned object contains *all* of the file data
555 """
Greg Steindd6eefb2000-07-18 09:09:48 +0000556 if mode != 'r' and mode != 'rb':
557 raise UnimplementedFileMode()
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000558
Greg Steindd6eefb2000-07-18 09:09:48 +0000559 msgbuf = ""
560 while 1:
561 try:
562 msgbuf = msgbuf + self.__ssl.read()
563 except socket.sslerror, msg:
564 break
565 return StringIO(msgbuf)
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000566
Greg Steindd6eefb2000-07-18 09:09:48 +0000567 def send(self, stuff, flags = 0):
568 return self.__ssl.write(stuff)
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000569
Greg Steindd6eefb2000-07-18 09:09:48 +0000570 def recv(self, len = 1024, flags = 0):
571 return self.__ssl.read(len)
Guido van Rossum23acc951994-02-21 16:36:04 +0000572
Greg Steindd6eefb2000-07-18 09:09:48 +0000573 def __getattr__(self, attr):
574 return getattr(self.__sock, attr)
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000575
Guido van Rossum23acc951994-02-21 16:36:04 +0000576
Greg Stein5e0fa402000-06-26 08:28:01 +0000577class HTTPSConnection(HTTPConnection):
Greg Steindd6eefb2000-07-18 09:09:48 +0000578 "This class allows communication via SSL."
Greg Stein5e0fa402000-06-26 08:28:01 +0000579
Greg Steindd6eefb2000-07-18 09:09:48 +0000580 default_port = HTTPS_PORT
Greg Stein5e0fa402000-06-26 08:28:01 +0000581
Greg Steindd6eefb2000-07-18 09:09:48 +0000582 def __init__(self, host, port=None, **x509):
583 keys = x509.keys()
584 try:
585 keys.remove('key_file')
586 except ValueError:
587 pass
588 try:
589 keys.remove('cert_file')
590 except ValueError:
591 pass
592 if keys:
593 raise IllegalKeywordArgument()
594 HTTPConnection.__init__(self, host, port)
595 self.key_file = x509.get('key_file')
596 self.cert_file = x509.get('cert_file')
Greg Stein5e0fa402000-06-26 08:28:01 +0000597
Greg Steindd6eefb2000-07-18 09:09:48 +0000598 def connect(self):
599 "Connect to a host on a given (SSL) port."
Greg Stein5e0fa402000-06-26 08:28:01 +0000600
Greg Steindd6eefb2000-07-18 09:09:48 +0000601 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
602 sock.connect((self.host, self.port))
603 ssl = socket.ssl(sock, self.key_file, self.cert_file)
604 self.sock = FakeSocket(sock, ssl)
Greg Stein5e0fa402000-06-26 08:28:01 +0000605
606
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000607class HTTP:
Greg Steindd6eefb2000-07-18 09:09:48 +0000608 "Compatibility class with httplib.py from 1.5."
Greg Stein5e0fa402000-06-26 08:28:01 +0000609
Greg Steindd6eefb2000-07-18 09:09:48 +0000610 _http_vsn = 10
611 _http_vsn_str = 'HTTP/1.0'
Greg Stein5e0fa402000-06-26 08:28:01 +0000612
Greg Steindd6eefb2000-07-18 09:09:48 +0000613 debuglevel = 0
Greg Stein5e0fa402000-06-26 08:28:01 +0000614
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000615 _connection_class = HTTPConnection
616
Greg Steindd6eefb2000-07-18 09:09:48 +0000617 def __init__(self, host='', port=None, **x509):
618 "Provide a default host, since the superclass requires one."
Greg Stein5e0fa402000-06-26 08:28:01 +0000619
Greg Steindd6eefb2000-07-18 09:09:48 +0000620 # some joker passed 0 explicitly, meaning default port
621 if port == 0:
622 port = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000623
Greg Steindd6eefb2000-07-18 09:09:48 +0000624 # Note that we may pass an empty string as the host; this will throw
625 # an error when we attempt to connect. Presumably, the client code
626 # will call connect before then, with a proper host.
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000627 self._conn = self._connection_class(host, port)
628 # set up delegation to flesh out interface
629 self.send = self._conn.send
630 self.putrequest = self._conn.putrequest
631 self.endheaders = self._conn.endheaders
Jeremy Hylton4d746fc2000-08-23 20:34:17 +0000632 self._conn._http_vsn = self._http_vsn
633 self._conn._http_vsn_str = self._http_vsn_str
Greg Stein5e0fa402000-06-26 08:28:01 +0000634
Greg Steindd6eefb2000-07-18 09:09:48 +0000635 # we never actually use these for anything, but we keep them here for
636 # compatibility with post-1.5.2 CVS.
637 self.key_file = x509.get('key_file')
638 self.cert_file = x509.get('cert_file')
Greg Stein5e0fa402000-06-26 08:28:01 +0000639
Greg Steindd6eefb2000-07-18 09:09:48 +0000640 self.file = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000641
Greg Steindd6eefb2000-07-18 09:09:48 +0000642 def connect(self, host=None, port=None):
643 "Accept arguments to set the host/port, since the superclass doesn't."
Greg Stein5e0fa402000-06-26 08:28:01 +0000644
Greg Steindd6eefb2000-07-18 09:09:48 +0000645 if host is not None:
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000646 self._conn._set_hostport(host, port)
647 self._conn.connect()
Greg Stein5e0fa402000-06-26 08:28:01 +0000648
Greg Steindd6eefb2000-07-18 09:09:48 +0000649 def set_debuglevel(self, debuglevel):
650 "The class no longer supports the debuglevel."
651 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000652
Greg Steindd6eefb2000-07-18 09:09:48 +0000653 def getfile(self):
654 "Provide a getfile, since the superclass' does not use this concept."
655 return self.file
Greg Stein5e0fa402000-06-26 08:28:01 +0000656
Greg Steindd6eefb2000-07-18 09:09:48 +0000657 def putheader(self, header, *values):
658 "The superclass allows only one value argument."
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000659 self._conn.putheader(header,
660 string.joinfields(values, '\r\n\t'))
Greg Stein5e0fa402000-06-26 08:28:01 +0000661
Greg Steindd6eefb2000-07-18 09:09:48 +0000662 def getreply(self):
663 """Compat definition since superclass does not define it.
Greg Stein5e0fa402000-06-26 08:28:01 +0000664
Greg Steindd6eefb2000-07-18 09:09:48 +0000665 Returns a tuple consisting of:
666 - server status code (e.g. '200' if all goes well)
667 - server "reason" corresponding to status code
668 - any RFC822 headers in the response from the server
669 """
670 try:
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000671 response = self._conn.getresponse()
Greg Steindd6eefb2000-07-18 09:09:48 +0000672 except BadStatusLine, e:
673 ### hmm. if getresponse() ever closes the socket on a bad request,
674 ### then we are going to have problems with self.sock
Greg Stein5e0fa402000-06-26 08:28:01 +0000675
Greg Steindd6eefb2000-07-18 09:09:48 +0000676 ### should we keep this behavior? do people use it?
677 # keep the socket open (as a file), and return it
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000678 self.file = self._conn.sock.makefile('rb', 0)
Greg Stein5e0fa402000-06-26 08:28:01 +0000679
Greg Steindd6eefb2000-07-18 09:09:48 +0000680 # close our socket -- we want to restart after any protocol error
681 self.close()
Greg Stein5e0fa402000-06-26 08:28:01 +0000682
Greg Steindd6eefb2000-07-18 09:09:48 +0000683 self.headers = None
684 return -1, e.line, None
Greg Stein5e0fa402000-06-26 08:28:01 +0000685
Greg Steindd6eefb2000-07-18 09:09:48 +0000686 self.headers = response.msg
687 self.file = response.fp
688 return response.status, response.reason, response.msg
Greg Stein5e0fa402000-06-26 08:28:01 +0000689
Greg Steindd6eefb2000-07-18 09:09:48 +0000690 def close(self):
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000691 self._conn.close()
Greg Stein5e0fa402000-06-26 08:28:01 +0000692
Greg Steindd6eefb2000-07-18 09:09:48 +0000693 # note that self.file == response.fp, which gets closed by the
694 # superclass. just clear the object ref here.
695 ### hmm. messy. if status==-1, then self.file is owned by us.
696 ### well... we aren't explicitly closing, but losing this ref will
697 ### do it
698 self.file = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000699
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000700if hasattr(socket, 'ssl'):
701 class HTTPS(HTTP):
702 """Compatibility with 1.5 httplib interface
703
704 Python 1.5.2 did not have an HTTPS class, but it defined an
705 interface for sending http requests that is also useful for
706 https.
707 """
708
709 _connection_class = HTTPSConnection
710
Greg Stein5e0fa402000-06-26 08:28:01 +0000711
712class HTTPException(Exception):
Greg Steindd6eefb2000-07-18 09:09:48 +0000713 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000714
715class NotConnected(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000716 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000717
718class UnknownProtocol(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000719 def __init__(self, version):
720 self.version = version
Greg Stein5e0fa402000-06-26 08:28:01 +0000721
722class UnknownTransferEncoding(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000723 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000724
725class IllegalKeywordArgument(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000726 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000727
728class UnimplementedFileMode(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000729 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000730
731class IncompleteRead(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000732 def __init__(self, partial):
733 self.partial = partial
Greg Stein5e0fa402000-06-26 08:28:01 +0000734
735class ImproperConnectionState(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000736 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000737
738class CannotSendRequest(ImproperConnectionState):
Greg Steindd6eefb2000-07-18 09:09:48 +0000739 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000740
741class CannotSendHeader(ImproperConnectionState):
Greg Steindd6eefb2000-07-18 09:09:48 +0000742 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000743
744class ResponseNotReady(ImproperConnectionState):
Greg Steindd6eefb2000-07-18 09:09:48 +0000745 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000746
747class BadStatusLine(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000748 def __init__(self, line):
749 self.line = line
Greg Stein5e0fa402000-06-26 08:28:01 +0000750
751# for backwards compatibility
752error = HTTPException
753
754
755#
756# snarfed from httplib.py for now...
757#
Guido van Rossum23acc951994-02-21 16:36:04 +0000758def test():
Guido van Rossum41999c11997-12-09 00:12:23 +0000759 """Test this module.
760
761 The test consists of retrieving and displaying the Python
762 home page, along with the error code and error string returned
763 by the www.python.org server.
Guido van Rossum41999c11997-12-09 00:12:23 +0000764 """
Greg Stein5e0fa402000-06-26 08:28:01 +0000765
Guido van Rossum41999c11997-12-09 00:12:23 +0000766 import sys
767 import getopt
768 opts, args = getopt.getopt(sys.argv[1:], 'd')
769 dl = 0
770 for o, a in opts:
771 if o == '-d': dl = dl + 1
772 host = 'www.python.org'
773 selector = '/'
774 if args[0:]: host = args[0]
775 if args[1:]: selector = args[1]
776 h = HTTP()
777 h.set_debuglevel(dl)
778 h.connect(host)
779 h.putrequest('GET', selector)
780 h.endheaders()
Greg Stein5e0fa402000-06-26 08:28:01 +0000781 status, reason, headers = h.getreply()
782 print 'status =', status
783 print 'reason =', reason
Guido van Rossum41999c11997-12-09 00:12:23 +0000784 print
785 if headers:
786 for header in headers.headers: print string.strip(header)
787 print
788 print h.getfile().read()
Greg Stein5e0fa402000-06-26 08:28:01 +0000789
790 if hasattr(socket, 'ssl'):
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000791 host = 'sourceforge.net'
Greg Steindd6eefb2000-07-18 09:09:48 +0000792 hs = HTTPS()
793 hs.connect(host)
794 hs.putrequest('GET', selector)
795 hs.endheaders()
796 status, reason, headers = hs.getreply()
797 print 'status =', status
798 print 'reason =', reason
799 print
800 if headers:
801 for header in headers.headers: print string.strip(header)
802 print
803 print hs.getfile().read()
Guido van Rossum23acc951994-02-21 16:36:04 +0000804
Guido van Rossuma0dfc7a1995-09-07 19:28:19 +0000805
Guido van Rossum23acc951994-02-21 16:36:04 +0000806if __name__ == '__main__':
Guido van Rossum41999c11997-12-09 00:12:23 +0000807 test()