blob: 2688359308958afc6bb43c7a9a1dc1ae5bcb3949 [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:
Jeremy Hylton30f86742000-09-18 22:50:38 +000090 def __init__(self, sock, debuglevel=0):
Greg Steindd6eefb2000-07-18 09:09:48 +000091 self.fp = sock.makefile('rb', 0)
Jeremy Hylton30f86742000-09-18 22:50:38 +000092 self.debuglevel = debuglevel
Greg Stein5e0fa402000-06-26 08:28:01 +000093
Greg Steindd6eefb2000-07-18 09:09:48 +000094 self.msg = None
Greg Stein5e0fa402000-06-26 08:28:01 +000095
Greg Steindd6eefb2000-07-18 09:09:48 +000096 # from the Status-Line of the response
97 self.version = _UNKNOWN # HTTP-Version
98 self.status = _UNKNOWN # Status-Code
99 self.reason = _UNKNOWN # Reason-Phrase
Greg Stein5e0fa402000-06-26 08:28:01 +0000100
Greg Steindd6eefb2000-07-18 09:09:48 +0000101 self.chunked = _UNKNOWN # is "chunked" being used?
102 self.chunk_left = _UNKNOWN # bytes left to read in current chunk
103 self.length = _UNKNOWN # number of bytes left in response
104 self.will_close = _UNKNOWN # conn will close at end of response
Greg Stein5e0fa402000-06-26 08:28:01 +0000105
Greg Steindd6eefb2000-07-18 09:09:48 +0000106 def begin(self):
107 if self.msg is not None:
108 # we've already started reading the response
109 return
Greg Stein5e0fa402000-06-26 08:28:01 +0000110
Greg Stein5e0fa402000-06-26 08:28:01 +0000111 line = self.fp.readline()
Jeremy Hylton30f86742000-09-18 22:50:38 +0000112 if self.debuglevel > 0:
113 print "reply:", repr(line)
Greg Steindd6eefb2000-07-18 09:09:48 +0000114 try:
115 [version, status, reason] = string.split(line, None, 2)
116 except ValueError:
117 try:
118 [version, status] = string.split(line, None, 1)
119 reason = ""
120 except ValueError:
Jeremy Hylton110941a2000-10-12 19:58:36 +0000121 version = "HTTP/0.9"
122 status = "200"
123 reason = ""
Greg Steindd6eefb2000-07-18 09:09:48 +0000124 if version[:5] != 'HTTP/':
125 self.close()
126 raise BadStatusLine(line)
Greg Stein5e0fa402000-06-26 08:28:01 +0000127
Greg Steindd6eefb2000-07-18 09:09:48 +0000128 self.status = status = int(status)
129 self.reason = string.strip(reason)
Greg Stein5e0fa402000-06-26 08:28:01 +0000130
Greg Steindd6eefb2000-07-18 09:09:48 +0000131 if version == 'HTTP/1.0':
132 self.version = 10
Jeremy Hylton110941a2000-10-12 19:58:36 +0000133 elif version.startswith('HTTP/1.'):
Greg Steindd6eefb2000-07-18 09:09:48 +0000134 self.version = 11 # use HTTP/1.1 code for HTTP/1.x where x>=1
Jeremy Hylton110941a2000-10-12 19:58:36 +0000135 elif version == 'HTTP/0.9':
136 self.version = 9
Greg Steindd6eefb2000-07-18 09:09:48 +0000137 else:
138 raise UnknownProtocol(version)
Greg Stein5e0fa402000-06-26 08:28:01 +0000139
Jeremy Hylton110941a2000-10-12 19:58:36 +0000140 if self.version == 9:
141 self.msg = mimetools.Message(StringIO())
142 return
143
Greg Steindd6eefb2000-07-18 09:09:48 +0000144 self.msg = mimetools.Message(self.fp, 0)
Jeremy Hylton30f86742000-09-18 22:50:38 +0000145 if self.debuglevel > 0:
146 for hdr in self.msg.headers:
147 print "header:", hdr,
Greg Stein5e0fa402000-06-26 08:28:01 +0000148
Greg Steindd6eefb2000-07-18 09:09:48 +0000149 # don't let the msg keep an fp
150 self.msg.fp = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000151
Greg Steindd6eefb2000-07-18 09:09:48 +0000152 # are we using the chunked-style of transfer encoding?
153 tr_enc = self.msg.getheader('transfer-encoding')
154 if tr_enc:
155 if string.lower(tr_enc) != 'chunked':
156 raise UnknownTransferEncoding()
157 self.chunked = 1
158 self.chunk_left = None
159 else:
160 self.chunked = 0
Greg Stein5e0fa402000-06-26 08:28:01 +0000161
Greg Steindd6eefb2000-07-18 09:09:48 +0000162 # will the connection close at the end of the response?
163 conn = self.msg.getheader('connection')
164 if conn:
165 conn = string.lower(conn)
166 # a "Connection: close" will always close the connection. if we
167 # don't see that and this is not HTTP/1.1, then the connection will
168 # close unless we see a Keep-Alive header.
169 self.will_close = string.find(conn, 'close') != -1 or \
170 ( self.version != 11 and \
171 not self.msg.getheader('keep-alive') )
172 else:
173 # for HTTP/1.1, the connection will always remain open
174 # otherwise, it will remain open IFF we see a Keep-Alive header
175 self.will_close = self.version != 11 and \
176 not self.msg.getheader('keep-alive')
Greg Stein5e0fa402000-06-26 08:28:01 +0000177
Greg Steindd6eefb2000-07-18 09:09:48 +0000178 # do we have a Content-Length?
179 # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
180 length = self.msg.getheader('content-length')
181 if length and not self.chunked:
Jeremy Hylton30a81812000-09-14 20:34:27 +0000182 try:
183 self.length = int(length)
184 except ValueError:
185 self.length = None
Greg Steindd6eefb2000-07-18 09:09:48 +0000186 else:
187 self.length = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000188
Greg Steindd6eefb2000-07-18 09:09:48 +0000189 # does the body have a fixed length? (of zero)
190 if (status == 204 or # No Content
191 status == 304 or # Not Modified
192 100 <= status < 200): # 1xx codes
193 self.length = 0
Greg Stein5e0fa402000-06-26 08:28:01 +0000194
Greg Steindd6eefb2000-07-18 09:09:48 +0000195 # if the connection remains open, and we aren't using chunked, and
196 # a content-length was not provided, then assume that the connection
197 # WILL close.
198 if not self.will_close and \
199 not self.chunked and \
200 self.length is None:
201 self.will_close = 1
Greg Stein5e0fa402000-06-26 08:28:01 +0000202
Greg Steindd6eefb2000-07-18 09:09:48 +0000203 def close(self):
204 if self.fp:
205 self.fp.close()
206 self.fp = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000207
Greg Steindd6eefb2000-07-18 09:09:48 +0000208 def isclosed(self):
209 # NOTE: it is possible that we will not ever call self.close(). This
210 # case occurs when will_close is TRUE, length is None, and we
211 # read up to the last byte, but NOT past it.
212 #
213 # IMPLIES: if will_close is FALSE, then self.close() will ALWAYS be
214 # called, meaning self.isclosed() is meaningful.
215 return self.fp is None
216
217 def read(self, amt=None):
218 if self.fp is None:
219 return ''
220
221 if self.chunked:
222 chunk_left = self.chunk_left
223 value = ''
224 while 1:
225 if chunk_left is None:
226 line = self.fp.readline()
227 i = string.find(line, ';')
228 if i >= 0:
229 line = line[:i] # strip chunk-extensions
230 chunk_left = string.atoi(line, 16)
231 if chunk_left == 0:
232 break
233 if amt is None:
234 value = value + self._safe_read(chunk_left)
235 elif amt < chunk_left:
236 value = value + self._safe_read(amt)
237 self.chunk_left = chunk_left - amt
238 return value
239 elif amt == chunk_left:
240 value = value + self._safe_read(amt)
241 self._safe_read(2) # toss the CRLF at the end of the chunk
242 self.chunk_left = None
243 return value
244 else:
245 value = value + self._safe_read(chunk_left)
246 amt = amt - chunk_left
247
248 # we read the whole chunk, get another
249 self._safe_read(2) # toss the CRLF at the end of the chunk
250 chunk_left = None
251
252 # read and discard trailer up to the CRLF terminator
253 ### note: we shouldn't have any trailers!
254 while 1:
255 line = self.fp.readline()
256 if line == '\r\n':
257 break
258
259 # we read everything; close the "file"
260 self.close()
261
262 return value
263
264 elif amt is None:
265 # unbounded read
266 if self.will_close:
267 s = self.fp.read()
268 else:
269 s = self._safe_read(self.length)
270 self.close() # we read everything
271 return s
272
273 if self.length is not None:
274 if amt > self.length:
275 # clip the read to the "end of response"
276 amt = self.length
277 self.length = self.length - amt
278
279 # we do not use _safe_read() here because this may be a .will_close
280 # connection, and the user is reading more bytes than will be provided
281 # (for example, reading in 1k chunks)
282 s = self.fp.read(amt)
283
Greg Steindd6eefb2000-07-18 09:09:48 +0000284 return s
285
286 def _safe_read(self, amt):
287 """Read the number of bytes requested, compensating for partial reads.
288
289 Normally, we have a blocking socket, but a read() can be interrupted
290 by a signal (resulting in a partial read).
291
292 Note that we cannot distinguish between EOF and an interrupt when zero
293 bytes have been read. IncompleteRead() will be raised in this
294 situation.
295
296 This function should be used when <amt> bytes "should" be present for
297 reading. If the bytes are truly not available (due to EOF), then the
298 IncompleteRead exception can be used to detect the problem.
299 """
300 s = ''
301 while amt > 0:
302 chunk = self.fp.read(amt)
303 if not chunk:
304 raise IncompleteRead(s)
305 s = s + chunk
306 amt = amt - len(chunk)
307 return s
308
309 def getheader(self, name, default=None):
310 if self.msg is None:
311 raise ResponseNotReady()
312 return self.msg.getheader(name, default)
Greg Stein5e0fa402000-06-26 08:28:01 +0000313
314
315class HTTPConnection:
316
Greg Steindd6eefb2000-07-18 09:09:48 +0000317 _http_vsn = 11
318 _http_vsn_str = 'HTTP/1.1'
Greg Stein5e0fa402000-06-26 08:28:01 +0000319
Greg Steindd6eefb2000-07-18 09:09:48 +0000320 response_class = HTTPResponse
321 default_port = HTTP_PORT
322 auto_open = 1
Jeremy Hylton30f86742000-09-18 22:50:38 +0000323 debuglevel = 0
Greg Stein5e0fa402000-06-26 08:28:01 +0000324
Greg Steindd6eefb2000-07-18 09:09:48 +0000325 def __init__(self, host, port=None):
326 self.sock = None
327 self.__response = None
328 self.__state = _CS_IDLE
Greg Stein5e0fa402000-06-26 08:28:01 +0000329
Greg Steindd6eefb2000-07-18 09:09:48 +0000330 self._set_hostport(host, port)
Greg Stein5e0fa402000-06-26 08:28:01 +0000331
Greg Steindd6eefb2000-07-18 09:09:48 +0000332 def _set_hostport(self, host, port):
333 if port is None:
334 i = string.find(host, ':')
335 if i >= 0:
336 port = int(host[i+1:])
337 host = host[:i]
338 else:
339 port = self.default_port
340 self.host = host
341 self.port = port
Greg Stein5e0fa402000-06-26 08:28:01 +0000342
Jeremy Hylton30f86742000-09-18 22:50:38 +0000343 def set_debuglevel(self, level):
344 self.debuglevel = level
345
Greg Steindd6eefb2000-07-18 09:09:48 +0000346 def connect(self):
347 """Connect to the host and port specified in __init__."""
348 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Jeremy Hylton30f86742000-09-18 22:50:38 +0000349 if self.debuglevel > 0:
350 print "connect: (%s, %s)" % (self.host, self.port)
Greg Steindd6eefb2000-07-18 09:09:48 +0000351 self.sock.connect((self.host, self.port))
Greg Stein5e0fa402000-06-26 08:28:01 +0000352
Greg Steindd6eefb2000-07-18 09:09:48 +0000353 def close(self):
354 """Close the connection to the HTTP server."""
355 if self.sock:
356 self.sock.close() # close it manually... there may be other refs
357 self.sock = None
358 if self.__response:
359 self.__response.close()
360 self.__response = None
361 self.__state = _CS_IDLE
Greg Stein5e0fa402000-06-26 08:28:01 +0000362
Greg Steindd6eefb2000-07-18 09:09:48 +0000363 def send(self, str):
364 """Send `str' to the server."""
365 if self.sock is None:
366 if self.auto_open:
367 self.connect()
368 else:
369 raise NotConnected()
Greg Stein5e0fa402000-06-26 08:28:01 +0000370
Greg Steindd6eefb2000-07-18 09:09:48 +0000371 # send the data to the server. if we get a broken pipe, then close
372 # the socket. we want to reconnect when somebody tries to send again.
373 #
374 # NOTE: we DO propagate the error, though, because we cannot simply
375 # ignore the error... the caller will know if they can retry.
Jeremy Hylton30f86742000-09-18 22:50:38 +0000376 if self.debuglevel > 0:
377 print "send:", repr(str)
Greg Steindd6eefb2000-07-18 09:09:48 +0000378 try:
379 self.sock.send(str)
380 except socket.error, v:
381 if v[0] == 32: # Broken pipe
382 self.close()
383 raise
Greg Stein5e0fa402000-06-26 08:28:01 +0000384
Greg Steindd6eefb2000-07-18 09:09:48 +0000385 def putrequest(self, method, url):
386 """Send a request to the server.
Greg Stein5e0fa402000-06-26 08:28:01 +0000387
Greg Steindd6eefb2000-07-18 09:09:48 +0000388 `method' specifies an HTTP request method, e.g. 'GET'.
389 `url' specifies the object being requested, e.g. '/index.html'.
390 """
Greg Stein5e0fa402000-06-26 08:28:01 +0000391
Greg Steindd6eefb2000-07-18 09:09:48 +0000392 # check if a prior response has been completed
393 if self.__response and self.__response.isclosed():
394 self.__response = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000395
Greg Steindd6eefb2000-07-18 09:09:48 +0000396 #
397 # in certain cases, we cannot issue another request on this connection.
398 # this occurs when:
399 # 1) we are in the process of sending a request. (_CS_REQ_STARTED)
400 # 2) a response to a previous request has signalled that it is going
401 # to close the connection upon completion.
402 # 3) the headers for the previous response have not been read, thus
403 # we cannot determine whether point (2) is true. (_CS_REQ_SENT)
404 #
405 # if there is no prior response, then we can request at will.
406 #
407 # if point (2) is true, then we will have passed the socket to the
408 # response (effectively meaning, "there is no prior response"), and
409 # will open a new one when a new request is made.
410 #
411 # Note: if a prior response exists, then we *can* start a new request.
412 # We are not allowed to begin fetching the response to this new
413 # request, however, until that prior response is complete.
414 #
415 if self.__state == _CS_IDLE:
416 self.__state = _CS_REQ_STARTED
417 else:
418 raise CannotSendRequest()
Greg Stein5e0fa402000-06-26 08:28:01 +0000419
Greg Steindd6eefb2000-07-18 09:09:48 +0000420 if not url:
421 url = '/'
422 str = '%s %s %s\r\n' % (method, url, self._http_vsn_str)
Greg Stein5e0fa402000-06-26 08:28:01 +0000423
Greg Steindd6eefb2000-07-18 09:09:48 +0000424 try:
425 self.send(str)
426 except socket.error, v:
427 # trap 'Broken pipe' if we're allowed to automatically reconnect
428 if v[0] != 32 or not self.auto_open:
429 raise
430 # try one more time (the socket was closed; this will reopen)
431 self.send(str)
Greg Stein5e0fa402000-06-26 08:28:01 +0000432
Greg Steindd6eefb2000-07-18 09:09:48 +0000433 if self._http_vsn == 11:
434 # Issue some standard headers for better HTTP/1.1 compliance
Greg Stein5e0fa402000-06-26 08:28:01 +0000435
Greg Steindd6eefb2000-07-18 09:09:48 +0000436 # this header is issued *only* for HTTP/1.1 connections. more
437 # specifically, this means it is only issued when the client uses
438 # the new HTTPConnection() class. backwards-compat clients will
439 # be using HTTP/1.0 and those clients may be issuing this header
440 # themselves. we should NOT issue it twice; some web servers (such
441 # as Apache) barf when they see two Host: headers
442 self.putheader('Host', self.host)
Greg Stein5e0fa402000-06-26 08:28:01 +0000443
Greg Steindd6eefb2000-07-18 09:09:48 +0000444 # note: we are assuming that clients will not attempt to set these
445 # headers since *this* library must deal with the
446 # consequences. this also means that when the supporting
447 # libraries are updated to recognize other forms, then this
448 # code should be changed (removed or updated).
Greg Stein5e0fa402000-06-26 08:28:01 +0000449
Greg Steindd6eefb2000-07-18 09:09:48 +0000450 # we only want a Content-Encoding of "identity" since we don't
451 # support encodings such as x-gzip or x-deflate.
452 self.putheader('Accept-Encoding', 'identity')
Greg Stein5e0fa402000-06-26 08:28:01 +0000453
Greg Steindd6eefb2000-07-18 09:09:48 +0000454 # we can accept "chunked" Transfer-Encodings, but no others
455 # NOTE: no TE header implies *only* "chunked"
456 #self.putheader('TE', 'chunked')
Greg Stein5e0fa402000-06-26 08:28:01 +0000457
Greg Steindd6eefb2000-07-18 09:09:48 +0000458 # if TE is supplied in the header, then it must appear in a
459 # Connection header.
460 #self.putheader('Connection', 'TE')
Greg Stein5e0fa402000-06-26 08:28:01 +0000461
Greg Steindd6eefb2000-07-18 09:09:48 +0000462 else:
463 # For HTTP/1.0, the server will assume "not chunked"
464 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000465
Greg Steindd6eefb2000-07-18 09:09:48 +0000466 def putheader(self, header, value):
467 """Send a request header line to the server.
Greg Stein5e0fa402000-06-26 08:28:01 +0000468
Greg Steindd6eefb2000-07-18 09:09:48 +0000469 For example: h.putheader('Accept', 'text/html')
470 """
471 if self.__state != _CS_REQ_STARTED:
472 raise CannotSendHeader()
Greg Stein5e0fa402000-06-26 08:28:01 +0000473
Greg Steindd6eefb2000-07-18 09:09:48 +0000474 str = '%s: %s\r\n' % (header, value)
475 self.send(str)
Greg Stein5e0fa402000-06-26 08:28:01 +0000476
Greg Steindd6eefb2000-07-18 09:09:48 +0000477 def endheaders(self):
478 """Indicate that the last header line has been sent to the server."""
Greg Stein5e0fa402000-06-26 08:28:01 +0000479
Greg Steindd6eefb2000-07-18 09:09:48 +0000480 if self.__state == _CS_REQ_STARTED:
481 self.__state = _CS_REQ_SENT
482 else:
483 raise CannotSendHeader()
Greg Stein5e0fa402000-06-26 08:28:01 +0000484
Greg Steindd6eefb2000-07-18 09:09:48 +0000485 self.send('\r\n')
Greg Stein5e0fa402000-06-26 08:28:01 +0000486
Greg Steindd6eefb2000-07-18 09:09:48 +0000487 def request(self, method, url, body=None, headers={}):
488 """Send a complete request to the server."""
Greg Stein5e0fa402000-06-26 08:28:01 +0000489
Greg Steindd6eefb2000-07-18 09:09:48 +0000490 try:
491 self._send_request(method, url, body, headers)
492 except socket.error, v:
493 # trap 'Broken pipe' if we're allowed to automatically reconnect
494 if v[0] != 32 or not self.auto_open:
495 raise
496 # try one more time
497 self._send_request(method, url, body, headers)
Greg Stein5e0fa402000-06-26 08:28:01 +0000498
Greg Steindd6eefb2000-07-18 09:09:48 +0000499 def _send_request(self, method, url, body, headers):
500 self.putrequest(method, url)
Greg Stein5e0fa402000-06-26 08:28:01 +0000501
Greg Steindd6eefb2000-07-18 09:09:48 +0000502 if body:
503 self.putheader('Content-Length', str(len(body)))
504 for hdr, value in headers.items():
505 self.putheader(hdr, value)
506 self.endheaders()
Greg Stein5e0fa402000-06-26 08:28:01 +0000507
Greg Steindd6eefb2000-07-18 09:09:48 +0000508 if body:
509 self.send(body)
Greg Stein5e0fa402000-06-26 08:28:01 +0000510
Greg Steindd6eefb2000-07-18 09:09:48 +0000511 def getresponse(self):
512 "Get the response from the server."
Greg Stein5e0fa402000-06-26 08:28:01 +0000513
Greg Steindd6eefb2000-07-18 09:09:48 +0000514 # check if a prior response has been completed
515 if self.__response and self.__response.isclosed():
516 self.__response = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000517
Greg Steindd6eefb2000-07-18 09:09:48 +0000518 #
519 # if a prior response exists, then it must be completed (otherwise, we
520 # cannot read this response's header to determine the connection-close
521 # behavior)
522 #
523 # note: if a prior response existed, but was connection-close, then the
524 # socket and response were made independent of this HTTPConnection
525 # object since a new request requires that we open a whole new
526 # connection
527 #
528 # this means the prior response had one of two states:
529 # 1) will_close: this connection was reset and the prior socket and
530 # response operate independently
531 # 2) persistent: the response was retained and we await its
532 # isclosed() status to become true.
533 #
534 if self.__state != _CS_REQ_SENT or self.__response:
535 raise ResponseNotReady()
Greg Stein5e0fa402000-06-26 08:28:01 +0000536
Jeremy Hylton30f86742000-09-18 22:50:38 +0000537 if self.debuglevel > 0:
538 response = self.response_class(self.sock, self.debuglevel)
539 else:
540 response = self.response_class(self.sock)
Greg Stein5e0fa402000-06-26 08:28:01 +0000541
Greg Steindd6eefb2000-07-18 09:09:48 +0000542 response.begin()
543 self.__state = _CS_IDLE
Greg Stein5e0fa402000-06-26 08:28:01 +0000544
Greg Steindd6eefb2000-07-18 09:09:48 +0000545 if response.will_close:
546 # this effectively passes the connection to the response
547 self.close()
548 else:
549 # remember this, so we can tell when it is complete
550 self.__response = response
Greg Stein5e0fa402000-06-26 08:28:01 +0000551
Greg Steindd6eefb2000-07-18 09:09:48 +0000552 return response
Greg Stein5e0fa402000-06-26 08:28:01 +0000553
554
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000555class FakeSocket:
Greg Steindd6eefb2000-07-18 09:09:48 +0000556 def __init__(self, sock, ssl):
557 self.__sock = sock
558 self.__ssl = ssl
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000559
Jeremy Hylton4d746fc2000-08-23 20:34:17 +0000560 def makefile(self, mode, bufsize=None):
561 """Return a readable file-like object with data from socket.
562
563 This method offers only partial support for the makefile
564 interface of a real socket. It only supports modes 'r' and
565 'rb' and the bufsize argument is ignored.
566
567 The returned object contains *all* of the file data
568 """
Greg Steindd6eefb2000-07-18 09:09:48 +0000569 if mode != 'r' and mode != 'rb':
570 raise UnimplementedFileMode()
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000571
Greg Steindd6eefb2000-07-18 09:09:48 +0000572 msgbuf = ""
573 while 1:
574 try:
575 msgbuf = msgbuf + self.__ssl.read()
576 except socket.sslerror, msg:
577 break
578 return StringIO(msgbuf)
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000579
Greg Steindd6eefb2000-07-18 09:09:48 +0000580 def send(self, stuff, flags = 0):
581 return self.__ssl.write(stuff)
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000582
Greg Steindd6eefb2000-07-18 09:09:48 +0000583 def recv(self, len = 1024, flags = 0):
584 return self.__ssl.read(len)
Guido van Rossum23acc951994-02-21 16:36:04 +0000585
Greg Steindd6eefb2000-07-18 09:09:48 +0000586 def __getattr__(self, attr):
587 return getattr(self.__sock, attr)
Guido van Rossum09c8b6c1999-12-07 21:37:17 +0000588
Guido van Rossum23acc951994-02-21 16:36:04 +0000589
Greg Stein5e0fa402000-06-26 08:28:01 +0000590class HTTPSConnection(HTTPConnection):
Greg Steindd6eefb2000-07-18 09:09:48 +0000591 "This class allows communication via SSL."
Greg Stein5e0fa402000-06-26 08:28:01 +0000592
Greg Steindd6eefb2000-07-18 09:09:48 +0000593 default_port = HTTPS_PORT
Greg Stein5e0fa402000-06-26 08:28:01 +0000594
Greg Steindd6eefb2000-07-18 09:09:48 +0000595 def __init__(self, host, port=None, **x509):
596 keys = x509.keys()
597 try:
598 keys.remove('key_file')
599 except ValueError:
600 pass
601 try:
602 keys.remove('cert_file')
603 except ValueError:
604 pass
605 if keys:
606 raise IllegalKeywordArgument()
607 HTTPConnection.__init__(self, host, port)
608 self.key_file = x509.get('key_file')
609 self.cert_file = x509.get('cert_file')
Greg Stein5e0fa402000-06-26 08:28:01 +0000610
Greg Steindd6eefb2000-07-18 09:09:48 +0000611 def connect(self):
612 "Connect to a host on a given (SSL) port."
Greg Stein5e0fa402000-06-26 08:28:01 +0000613
Greg Steindd6eefb2000-07-18 09:09:48 +0000614 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
615 sock.connect((self.host, self.port))
616 ssl = socket.ssl(sock, self.key_file, self.cert_file)
617 self.sock = FakeSocket(sock, ssl)
Greg Stein5e0fa402000-06-26 08:28:01 +0000618
619
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000620class HTTP:
Greg Steindd6eefb2000-07-18 09:09:48 +0000621 "Compatibility class with httplib.py from 1.5."
Greg Stein5e0fa402000-06-26 08:28:01 +0000622
Greg Steindd6eefb2000-07-18 09:09:48 +0000623 _http_vsn = 10
624 _http_vsn_str = 'HTTP/1.0'
Greg Stein5e0fa402000-06-26 08:28:01 +0000625
Greg Steindd6eefb2000-07-18 09:09:48 +0000626 debuglevel = 0
Greg Stein5e0fa402000-06-26 08:28:01 +0000627
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000628 _connection_class = HTTPConnection
629
Greg Steindd6eefb2000-07-18 09:09:48 +0000630 def __init__(self, host='', port=None, **x509):
631 "Provide a default host, since the superclass requires one."
Greg Stein5e0fa402000-06-26 08:28:01 +0000632
Greg Steindd6eefb2000-07-18 09:09:48 +0000633 # some joker passed 0 explicitly, meaning default port
634 if port == 0:
635 port = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000636
Greg Steindd6eefb2000-07-18 09:09:48 +0000637 # Note that we may pass an empty string as the host; this will throw
638 # an error when we attempt to connect. Presumably, the client code
639 # will call connect before then, with a proper host.
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000640 self._conn = self._connection_class(host, port)
641 # set up delegation to flesh out interface
642 self.send = self._conn.send
643 self.putrequest = self._conn.putrequest
644 self.endheaders = self._conn.endheaders
Jeremy Hylton4d746fc2000-08-23 20:34:17 +0000645 self._conn._http_vsn = self._http_vsn
646 self._conn._http_vsn_str = self._http_vsn_str
Greg Stein5e0fa402000-06-26 08:28:01 +0000647
Greg Steindd6eefb2000-07-18 09:09:48 +0000648 # we never actually use these for anything, but we keep them here for
649 # compatibility with post-1.5.2 CVS.
650 self.key_file = x509.get('key_file')
651 self.cert_file = x509.get('cert_file')
Greg Stein5e0fa402000-06-26 08:28:01 +0000652
Greg Steindd6eefb2000-07-18 09:09:48 +0000653 self.file = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000654
Greg Steindd6eefb2000-07-18 09:09:48 +0000655 def connect(self, host=None, port=None):
656 "Accept arguments to set the host/port, since the superclass doesn't."
Greg Stein5e0fa402000-06-26 08:28:01 +0000657
Greg Steindd6eefb2000-07-18 09:09:48 +0000658 if host is not None:
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000659 self._conn._set_hostport(host, port)
660 self._conn.connect()
Greg Stein5e0fa402000-06-26 08:28:01 +0000661
Greg Steindd6eefb2000-07-18 09:09:48 +0000662 def set_debuglevel(self, debuglevel):
Jeremy Hylton30f86742000-09-18 22:50:38 +0000663 self._conn.set_debuglevel(debuglevel)
Greg Stein5e0fa402000-06-26 08:28:01 +0000664
Greg Steindd6eefb2000-07-18 09:09:48 +0000665 def getfile(self):
666 "Provide a getfile, since the superclass' does not use this concept."
667 return self.file
Greg Stein5e0fa402000-06-26 08:28:01 +0000668
Greg Steindd6eefb2000-07-18 09:09:48 +0000669 def putheader(self, header, *values):
670 "The superclass allows only one value argument."
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000671 self._conn.putheader(header,
672 string.joinfields(values, '\r\n\t'))
Greg Stein5e0fa402000-06-26 08:28:01 +0000673
Greg Steindd6eefb2000-07-18 09:09:48 +0000674 def getreply(self):
675 """Compat definition since superclass does not define it.
Greg Stein5e0fa402000-06-26 08:28:01 +0000676
Greg Steindd6eefb2000-07-18 09:09:48 +0000677 Returns a tuple consisting of:
678 - server status code (e.g. '200' if all goes well)
679 - server "reason" corresponding to status code
680 - any RFC822 headers in the response from the server
681 """
682 try:
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000683 response = self._conn.getresponse()
Greg Steindd6eefb2000-07-18 09:09:48 +0000684 except BadStatusLine, e:
685 ### hmm. if getresponse() ever closes the socket on a bad request,
686 ### then we are going to have problems with self.sock
Greg Stein5e0fa402000-06-26 08:28:01 +0000687
Greg Steindd6eefb2000-07-18 09:09:48 +0000688 ### should we keep this behavior? do people use it?
689 # keep the socket open (as a file), and return it
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000690 self.file = self._conn.sock.makefile('rb', 0)
Greg Stein5e0fa402000-06-26 08:28:01 +0000691
Greg Steindd6eefb2000-07-18 09:09:48 +0000692 # close our socket -- we want to restart after any protocol error
693 self.close()
Greg Stein5e0fa402000-06-26 08:28:01 +0000694
Greg Steindd6eefb2000-07-18 09:09:48 +0000695 self.headers = None
696 return -1, e.line, None
Greg Stein5e0fa402000-06-26 08:28:01 +0000697
Greg Steindd6eefb2000-07-18 09:09:48 +0000698 self.headers = response.msg
699 self.file = response.fp
700 return response.status, response.reason, response.msg
Greg Stein5e0fa402000-06-26 08:28:01 +0000701
Greg Steindd6eefb2000-07-18 09:09:48 +0000702 def close(self):
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000703 self._conn.close()
Greg Stein5e0fa402000-06-26 08:28:01 +0000704
Greg Steindd6eefb2000-07-18 09:09:48 +0000705 # note that self.file == response.fp, which gets closed by the
706 # superclass. just clear the object ref here.
707 ### hmm. messy. if status==-1, then self.file is owned by us.
708 ### well... we aren't explicitly closing, but losing this ref will
709 ### do it
710 self.file = None
Greg Stein5e0fa402000-06-26 08:28:01 +0000711
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000712if hasattr(socket, 'ssl'):
713 class HTTPS(HTTP):
714 """Compatibility with 1.5 httplib interface
715
716 Python 1.5.2 did not have an HTTPS class, but it defined an
717 interface for sending http requests that is also useful for
718 https.
719 """
720
Martin v. Löwisd7bf9742000-09-21 22:09:47 +0000721 _connection_class = HTTPSConnection
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000722
Greg Stein5e0fa402000-06-26 08:28:01 +0000723
724class HTTPException(Exception):
Greg Steindd6eefb2000-07-18 09:09:48 +0000725 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000726
727class NotConnected(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000728 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000729
730class UnknownProtocol(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000731 def __init__(self, version):
732 self.version = version
Greg Stein5e0fa402000-06-26 08:28:01 +0000733
734class UnknownTransferEncoding(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000735 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000736
737class IllegalKeywordArgument(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000738 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000739
740class UnimplementedFileMode(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000741 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000742
743class IncompleteRead(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000744 def __init__(self, partial):
745 self.partial = partial
Greg Stein5e0fa402000-06-26 08:28:01 +0000746
747class ImproperConnectionState(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000748 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000749
750class CannotSendRequest(ImproperConnectionState):
Greg Steindd6eefb2000-07-18 09:09:48 +0000751 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000752
753class CannotSendHeader(ImproperConnectionState):
Greg Steindd6eefb2000-07-18 09:09:48 +0000754 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000755
756class ResponseNotReady(ImproperConnectionState):
Greg Steindd6eefb2000-07-18 09:09:48 +0000757 pass
Greg Stein5e0fa402000-06-26 08:28:01 +0000758
759class BadStatusLine(HTTPException):
Greg Steindd6eefb2000-07-18 09:09:48 +0000760 def __init__(self, line):
761 self.line = line
Greg Stein5e0fa402000-06-26 08:28:01 +0000762
763# for backwards compatibility
764error = HTTPException
765
766
767#
768# snarfed from httplib.py for now...
769#
Guido van Rossum23acc951994-02-21 16:36:04 +0000770def test():
Guido van Rossum41999c11997-12-09 00:12:23 +0000771 """Test this module.
772
773 The test consists of retrieving and displaying the Python
774 home page, along with the error code and error string returned
775 by the www.python.org server.
Guido van Rossum41999c11997-12-09 00:12:23 +0000776 """
Greg Stein5e0fa402000-06-26 08:28:01 +0000777
Guido van Rossum41999c11997-12-09 00:12:23 +0000778 import sys
779 import getopt
780 opts, args = getopt.getopt(sys.argv[1:], 'd')
781 dl = 0
782 for o, a in opts:
783 if o == '-d': dl = dl + 1
784 host = 'www.python.org'
785 selector = '/'
786 if args[0:]: host = args[0]
787 if args[1:]: selector = args[1]
788 h = HTTP()
789 h.set_debuglevel(dl)
790 h.connect(host)
791 h.putrequest('GET', selector)
792 h.endheaders()
Greg Stein5e0fa402000-06-26 08:28:01 +0000793 status, reason, headers = h.getreply()
794 print 'status =', status
795 print 'reason =', reason
Guido van Rossum41999c11997-12-09 00:12:23 +0000796 print
797 if headers:
798 for header in headers.headers: print string.strip(header)
799 print
800 print h.getfile().read()
Greg Stein5e0fa402000-06-26 08:28:01 +0000801
802 if hasattr(socket, 'ssl'):
Jeremy Hylton29b8d5a2000-08-01 17:33:32 +0000803 host = 'sourceforge.net'
Greg Steindd6eefb2000-07-18 09:09:48 +0000804 hs = HTTPS()
805 hs.connect(host)
806 hs.putrequest('GET', selector)
807 hs.endheaders()
808 status, reason, headers = hs.getreply()
809 print 'status =', status
810 print 'reason =', reason
811 print
812 if headers:
813 for header in headers.headers: print string.strip(header)
814 print
815 print hs.getfile().read()
Guido van Rossum23acc951994-02-21 16:36:04 +0000816
Guido van Rossuma0dfc7a1995-09-07 19:28:19 +0000817
Guido van Rossum23acc951994-02-21 16:36:04 +0000818if __name__ == '__main__':
Guido van Rossum41999c11997-12-09 00:12:23 +0000819 test()