Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / amd64 / lib / python2.4 / httplib.py
CommitLineData
920dae64
AT
1"""HTTP/1.1 client library
2
3<intro stuff goes here>
4<other stuff, too>
5
6HTTPConnection 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:
9
10 (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>
67"""
68
69import errno
70import mimetools
71import socket
72from urlparse import urlsplit
73
74try:
75 from cStringIO import StringIO
76except ImportError:
77 from StringIO import StringIO
78
79__all__ = ["HTTP", "HTTPResponse", "HTTPConnection", "HTTPSConnection",
80 "HTTPException", "NotConnected", "UnknownProtocol",
81 "UnknownTransferEncoding", "UnimplementedFileMode",
82 "IncompleteRead", "InvalidURL", "ImproperConnectionState",
83 "CannotSendRequest", "CannotSendHeader", "ResponseNotReady",
84 "BadStatusLine", "error"]
85
86HTTP_PORT = 80
87HTTPS_PORT = 443
88
89_UNKNOWN = 'UNKNOWN'
90
91# connection states
92_CS_IDLE = 'Idle'
93_CS_REQ_STARTED = 'Request-started'
94_CS_REQ_SENT = 'Request-sent'
95
96# status codes
97# informational
98CONTINUE = 100
99SWITCHING_PROTOCOLS = 101
100PROCESSING = 102
101
102# successful
103OK = 200
104CREATED = 201
105ACCEPTED = 202
106NON_AUTHORITATIVE_INFORMATION = 203
107NO_CONTENT = 204
108RESET_CONTENT = 205
109PARTIAL_CONTENT = 206
110MULTI_STATUS = 207
111IM_USED = 226
112
113# redirection
114MULTIPLE_CHOICES = 300
115MOVED_PERMANENTLY = 301
116FOUND = 302
117SEE_OTHER = 303
118NOT_MODIFIED = 304
119USE_PROXY = 305
120TEMPORARY_REDIRECT = 307
121
122# client error
123BAD_REQUEST = 400
124UNAUTHORIZED = 401
125PAYMENT_REQUIRED = 402
126FORBIDDEN = 403
127NOT_FOUND = 404
128METHOD_NOT_ALLOWED = 405
129NOT_ACCEPTABLE = 406
130PROXY_AUTHENTICATION_REQUIRED = 407
131REQUEST_TIMEOUT = 408
132CONFLICT = 409
133GONE = 410
134LENGTH_REQUIRED = 411
135PRECONDITION_FAILED = 412
136REQUEST_ENTITY_TOO_LARGE = 413
137REQUEST_URI_TOO_LONG = 414
138UNSUPPORTED_MEDIA_TYPE = 415
139REQUESTED_RANGE_NOT_SATISFIABLE = 416
140EXPECTATION_FAILED = 417
141UNPROCESSABLE_ENTITY = 422
142LOCKED = 423
143FAILED_DEPENDENCY = 424
144UPGRADE_REQUIRED = 426
145
146# server error
147INTERNAL_SERVER_ERROR = 500
148NOT_IMPLEMENTED = 501
149BAD_GATEWAY = 502
150SERVICE_UNAVAILABLE = 503
151GATEWAY_TIMEOUT = 504
152HTTP_VERSION_NOT_SUPPORTED = 505
153INSUFFICIENT_STORAGE = 507
154NOT_EXTENDED = 510
155
156class HTTPMessage(mimetools.Message):
157
158 def addheader(self, key, value):
159 """Add header for field key handling repeats."""
160 prev = self.dict.get(key)
161 if prev is None:
162 self.dict[key] = value
163 else:
164 combined = ", ".join((prev, value))
165 self.dict[key] = combined
166
167 def addcontinue(self, key, more):
168 """Add more field data from a continuation line."""
169 prev = self.dict[key]
170 self.dict[key] = prev + "\n " + more
171
172 def readheaders(self):
173 """Read header lines.
174
175 Read header lines up to the entirely blank line that terminates them.
176 The (normally blank) line that ends the headers is skipped, but not
177 included in the returned list. If a non-header line ends the headers,
178 (which is an error), an attempt is made to backspace over it; it is
179 never included in the returned list.
180
181 The variable self.status is set to the empty string if all went well,
182 otherwise it is an error message. The variable self.headers is a
183 completely uninterpreted list of lines contained in the header (so
184 printing them will reproduce the header exactly as it appears in the
185 file).
186
187 If multiple header fields with the same name occur, they are combined
188 according to the rules in RFC 2616 sec 4.2:
189
190 Appending each subsequent field-value to the first, each separated
191 by a comma. The order in which header fields with the same field-name
192 are received is significant to the interpretation of the combined
193 field value.
194 """
195 # XXX The implementation overrides the readheaders() method of
196 # rfc822.Message. The base class design isn't amenable to
197 # customized behavior here so the method here is a copy of the
198 # base class code with a few small changes.
199
200 self.dict = {}
201 self.unixfrom = ''
202 self.headers = hlist = []
203 self.status = ''
204 headerseen = ""
205 firstline = 1
206 startofline = unread = tell = None
207 if hasattr(self.fp, 'unread'):
208 unread = self.fp.unread
209 elif self.seekable:
210 tell = self.fp.tell
211 while True:
212 if tell:
213 try:
214 startofline = tell()
215 except IOError:
216 startofline = tell = None
217 self.seekable = 0
218 line = self.fp.readline()
219 if not line:
220 self.status = 'EOF in headers'
221 break
222 # Skip unix From name time lines
223 if firstline and line.startswith('From '):
224 self.unixfrom = self.unixfrom + line
225 continue
226 firstline = 0
227 if headerseen and line[0] in ' \t':
228 # XXX Not sure if continuation lines are handled properly
229 # for http and/or for repeating headers
230 # It's a continuation line.
231 hlist.append(line)
232 self.addcontinue(headerseen, line.strip())
233 continue
234 elif self.iscomment(line):
235 # It's a comment. Ignore it.
236 continue
237 elif self.islast(line):
238 # Note! No pushback here! The delimiter line gets eaten.
239 break
240 headerseen = self.isheader(line)
241 if headerseen:
242 # It's a legal header line, save it.
243 hlist.append(line)
244 self.addheader(headerseen, line[len(headerseen)+1:].strip())
245 continue
246 else:
247 # It's not a header line; throw it back and stop here.
248 if not self.dict:
249 self.status = 'No headers'
250 else:
251 self.status = 'Non-header line where header expected'
252 # Try to undo the read.
253 if unread:
254 unread(line)
255 elif tell:
256 self.fp.seek(startofline)
257 else:
258 self.status = self.status + '; bad seek'
259 break
260
261class HTTPResponse:
262
263 # strict: If true, raise BadStatusLine if the status line can't be
264 # parsed as a valid HTTP/1.0 or 1.1 status line. By default it is
265 # false because it prevents clients from talking to HTTP/0.9
266 # servers. Note that a response with a sufficiently corrupted
267 # status line will look like an HTTP/0.9 response.
268
269 # See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details.
270
271 def __init__(self, sock, debuglevel=0, strict=0, method=None):
272 self.fp = sock.makefile('rb', 0)
273 self.debuglevel = debuglevel
274 self.strict = strict
275 self._method = method
276
277 self.msg = None
278
279 # from the Status-Line of the response
280 self.version = _UNKNOWN # HTTP-Version
281 self.status = _UNKNOWN # Status-Code
282 self.reason = _UNKNOWN # Reason-Phrase
283
284 self.chunked = _UNKNOWN # is "chunked" being used?
285 self.chunk_left = _UNKNOWN # bytes left to read in current chunk
286 self.length = _UNKNOWN # number of bytes left in response
287 self.will_close = _UNKNOWN # conn will close at end of response
288
289 def _read_status(self):
290 # Initialize with Simple-Response defaults
291 line = self.fp.readline()
292 if self.debuglevel > 0:
293 print "reply:", repr(line)
294 if not line:
295 # Presumably, the server closed the connection before
296 # sending a valid response.
297 raise BadStatusLine(line)
298 try:
299 [version, status, reason] = line.split(None, 2)
300 except ValueError:
301 try:
302 [version, status] = line.split(None, 1)
303 reason = ""
304 except ValueError:
305 # empty version will cause next test to fail and status
306 # will be treated as 0.9 response.
307 version = ""
308 if not version.startswith('HTTP/'):
309 if self.strict:
310 self.close()
311 raise BadStatusLine(line)
312 else:
313 # assume it's a Simple-Response from an 0.9 server
314 self.fp = LineAndFileWrapper(line, self.fp)
315 return "HTTP/0.9", 200, ""
316
317 # The status code is a three-digit number
318 try:
319 status = int(status)
320 if status < 100 or status > 999:
321 raise BadStatusLine(line)
322 except ValueError:
323 raise BadStatusLine(line)
324 return version, status, reason
325
326 def begin(self):
327 if self.msg is not None:
328 # we've already started reading the response
329 return
330
331 # read until we get a non-100 response
332 while True:
333 version, status, reason = self._read_status()
334 if status != CONTINUE:
335 break
336 # skip the header from the 100 response
337 while True:
338 skip = self.fp.readline().strip()
339 if not skip:
340 break
341 if self.debuglevel > 0:
342 print "header:", skip
343
344 self.status = status
345 self.reason = reason.strip()
346 if version == 'HTTP/1.0':
347 self.version = 10
348 elif version.startswith('HTTP/1.'):
349 self.version = 11 # use HTTP/1.1 code for HTTP/1.x where x>=1
350 elif version == 'HTTP/0.9':
351 self.version = 9
352 else:
353 raise UnknownProtocol(version)
354
355 if self.version == 9:
356 self.length = None
357 self.chunked = 0
358 self.will_close = 1
359 self.msg = HTTPMessage(StringIO())
360 return
361
362 self.msg = HTTPMessage(self.fp, 0)
363 if self.debuglevel > 0:
364 for hdr in self.msg.headers:
365 print "header:", hdr,
366
367 # don't let the msg keep an fp
368 self.msg.fp = None
369
370 # are we using the chunked-style of transfer encoding?
371 tr_enc = self.msg.getheader('transfer-encoding')
372 if tr_enc and tr_enc.lower() == "chunked":
373 self.chunked = 1
374 self.chunk_left = None
375 else:
376 self.chunked = 0
377
378 # will the connection close at the end of the response?
379 self.will_close = self._check_close()
380
381 # do we have a Content-Length?
382 # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
383 length = self.msg.getheader('content-length')
384 if length and not self.chunked:
385 try:
386 self.length = int(length)
387 except ValueError:
388 self.length = None
389 else:
390 self.length = None
391
392 # does the body have a fixed length? (of zero)
393 if (status == NO_CONTENT or status == NOT_MODIFIED or
394 100 <= status < 200 or # 1xx codes
395 self._method == 'HEAD'):
396 self.length = 0
397
398 # if the connection remains open, and we aren't using chunked, and
399 # a content-length was not provided, then assume that the connection
400 # WILL close.
401 if not self.will_close and \
402 not self.chunked and \
403 self.length is None:
404 self.will_close = 1
405
406 def _check_close(self):
407 conn = self.msg.getheader('connection')
408 if self.version == 11:
409 # An HTTP/1.1 proxy is assumed to stay open unless
410 # explicitly closed.
411 conn = self.msg.getheader('connection')
412 if conn and "close" in conn.lower():
413 return True
414 return False
415
416 # Some HTTP/1.0 implementations have support for persistent
417 # connections, using rules different than HTTP/1.1.
418
419 # For older HTTP, Keep-Alive indiciates persistent connection.
420 if self.msg.getheader('keep-alive'):
421 return False
422
423 # At least Akamai returns a "Connection: Keep-Alive" header,
424 # which was supposed to be sent by the client.
425 if conn and "keep-alive" in conn.lower():
426 return False
427
428 # Proxy-Connection is a netscape hack.
429 pconn = self.msg.getheader('proxy-connection')
430 if pconn and "keep-alive" in pconn.lower():
431 return False
432
433 # otherwise, assume it will close
434 return True
435
436 def close(self):
437 if self.fp:
438 self.fp.close()
439 self.fp = None
440
441 def isclosed(self):
442 # NOTE: it is possible that we will not ever call self.close(). This
443 # case occurs when will_close is TRUE, length is None, and we
444 # read up to the last byte, but NOT past it.
445 #
446 # IMPLIES: if will_close is FALSE, then self.close() will ALWAYS be
447 # called, meaning self.isclosed() is meaningful.
448 return self.fp is None
449
450 # XXX It would be nice to have readline and __iter__ for this, too.
451
452 def read(self, amt=None):
453 if self.fp is None:
454 return ''
455
456 if self.chunked:
457 return self._read_chunked(amt)
458
459 if amt is None:
460 # unbounded read
461 if self.length is None:
462 s = self.fp.read()
463 else:
464 s = self._safe_read(self.length)
465 self.length = 0
466 self.close() # we read everything
467 return s
468
469 if self.length is not None:
470 if amt > self.length:
471 # clip the read to the "end of response"
472 amt = self.length
473
474 # we do not use _safe_read() here because this may be a .will_close
475 # connection, and the user is reading more bytes than will be provided
476 # (for example, reading in 1k chunks)
477 s = self.fp.read(amt)
478 if self.length is not None:
479 self.length -= len(s)
480
481 return s
482
483 def _read_chunked(self, amt):
484 assert self.chunked != _UNKNOWN
485 chunk_left = self.chunk_left
486 value = ''
487
488 # XXX This accumulates chunks by repeated string concatenation,
489 # which is not efficient as the number or size of chunks gets big.
490 while True:
491 if chunk_left is None:
492 line = self.fp.readline()
493 i = line.find(';')
494 if i >= 0:
495 line = line[:i] # strip chunk-extensions
496 chunk_left = int(line, 16)
497 if chunk_left == 0:
498 break
499 if amt is None:
500 value += self._safe_read(chunk_left)
501 elif amt < chunk_left:
502 value += self._safe_read(amt)
503 self.chunk_left = chunk_left - amt
504 return value
505 elif amt == chunk_left:
506 value += self._safe_read(amt)
507 self._safe_read(2) # toss the CRLF at the end of the chunk
508 self.chunk_left = None
509 return value
510 else:
511 value += self._safe_read(chunk_left)
512 amt -= chunk_left
513
514 # we read the whole chunk, get another
515 self._safe_read(2) # toss the CRLF at the end of the chunk
516 chunk_left = None
517
518 # read and discard trailer up to the CRLF terminator
519 ### note: we shouldn't have any trailers!
520 while True:
521 line = self.fp.readline()
522 if line == '\r\n':
523 break
524
525 # we read everything; close the "file"
526 self.close()
527
528 return value
529
530 def _safe_read(self, amt):
531 """Read the number of bytes requested, compensating for partial reads.
532
533 Normally, we have a blocking socket, but a read() can be interrupted
534 by a signal (resulting in a partial read).
535
536 Note that we cannot distinguish between EOF and an interrupt when zero
537 bytes have been read. IncompleteRead() will be raised in this
538 situation.
539
540 This function should be used when <amt> bytes "should" be present for
541 reading. If the bytes are truly not available (due to EOF), then the
542 IncompleteRead exception can be used to detect the problem.
543 """
544 s = ''
545 while amt > 0:
546 chunk = self.fp.read(amt)
547 if not chunk:
548 raise IncompleteRead(s)
549 s += chunk
550 amt -= len(chunk)
551 return s
552
553 def getheader(self, name, default=None):
554 if self.msg is None:
555 raise ResponseNotReady()
556 return self.msg.getheader(name, default)
557
558 def getheaders(self):
559 """Return list of (header, value) tuples."""
560 if self.msg is None:
561 raise ResponseNotReady()
562 return self.msg.items()
563
564
565class HTTPConnection:
566
567 _http_vsn = 11
568 _http_vsn_str = 'HTTP/1.1'
569
570 response_class = HTTPResponse
571 default_port = HTTP_PORT
572 auto_open = 1
573 debuglevel = 0
574 strict = 0
575
576 def __init__(self, host, port=None, strict=None):
577 self.sock = None
578 self._buffer = []
579 self.__response = None
580 self.__state = _CS_IDLE
581 self._method = None
582
583 self._set_hostport(host, port)
584 if strict is not None:
585 self.strict = strict
586
587 def _set_hostport(self, host, port):
588 if port is None:
589 i = host.rfind(':')
590 j = host.rfind(']') # ipv6 addresses have [...]
591 if i > j:
592 try:
593 port = int(host[i+1:])
594 except ValueError:
595 raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
596 host = host[:i]
597 else:
598 port = self.default_port
599 if host and host[0] == '[' and host[-1] == ']':
600 host = host[1:-1]
601 self.host = host
602 self.port = port
603
604 def set_debuglevel(self, level):
605 self.debuglevel = level
606
607 def connect(self):
608 """Connect to the host and port specified in __init__."""
609 msg = "getaddrinfo returns an empty list"
610 for res in socket.getaddrinfo(self.host, self.port, 0,
611 socket.SOCK_STREAM):
612 af, socktype, proto, canonname, sa = res
613 try:
614 self.sock = socket.socket(af, socktype, proto)
615 if self.debuglevel > 0:
616 print "connect: (%s, %s)" % (self.host, self.port)
617 self.sock.connect(sa)
618 except socket.error, msg:
619 if self.debuglevel > 0:
620 print 'connect fail:', (self.host, self.port)
621 if self.sock:
622 self.sock.close()
623 self.sock = None
624 continue
625 break
626 if not self.sock:
627 raise socket.error, msg
628
629 def close(self):
630 """Close the connection to the HTTP server."""
631 if self.sock:
632 self.sock.close() # close it manually... there may be other refs
633 self.sock = None
634 if self.__response:
635 self.__response.close()
636 self.__response = None
637 self.__state = _CS_IDLE
638
639 def send(self, str):
640 """Send `str' to the server."""
641 if self.sock is None:
642 if self.auto_open:
643 self.connect()
644 else:
645 raise NotConnected()
646
647 # send the data to the server. if we get a broken pipe, then close
648 # the socket. we want to reconnect when somebody tries to send again.
649 #
650 # NOTE: we DO propagate the error, though, because we cannot simply
651 # ignore the error... the caller will know if they can retry.
652 if self.debuglevel > 0:
653 print "send:", repr(str)
654 try:
655 self.sock.sendall(str)
656 except socket.error, v:
657 if v[0] == 32: # Broken pipe
658 self.close()
659 raise
660
661 def _output(self, s):
662 """Add a line of output to the current request buffer.
663
664 Assumes that the line does *not* end with \\r\\n.
665 """
666 self._buffer.append(s)
667
668 def _send_output(self):
669 """Send the currently buffered request and clear the buffer.
670
671 Appends an extra \\r\\n to the buffer.
672 """
673 self._buffer.extend(("", ""))
674 msg = "\r\n".join(self._buffer)
675 del self._buffer[:]
676 self.send(msg)
677
678 def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0):
679 """Send a request to the server.
680
681 `method' specifies an HTTP request method, e.g. 'GET'.
682 `url' specifies the object being requested, e.g. '/index.html'.
683 `skip_host' if True does not add automatically a 'Host:' header
684 `skip_accept_encoding' if True does not add automatically an
685 'Accept-Encoding:' header
686 """
687
688 # if a prior response has been completed, then forget about it.
689 if self.__response and self.__response.isclosed():
690 self.__response = None
691
692
693 # in certain cases, we cannot issue another request on this connection.
694 # this occurs when:
695 # 1) we are in the process of sending a request. (_CS_REQ_STARTED)
696 # 2) a response to a previous request has signalled that it is going
697 # to close the connection upon completion.
698 # 3) the headers for the previous response have not been read, thus
699 # we cannot determine whether point (2) is true. (_CS_REQ_SENT)
700 #
701 # if there is no prior response, then we can request at will.
702 #
703 # if point (2) is true, then we will have passed the socket to the
704 # response (effectively meaning, "there is no prior response"), and
705 # will open a new one when a new request is made.
706 #
707 # Note: if a prior response exists, then we *can* start a new request.
708 # We are not allowed to begin fetching the response to this new
709 # request, however, until that prior response is complete.
710 #
711 if self.__state == _CS_IDLE:
712 self.__state = _CS_REQ_STARTED
713 else:
714 raise CannotSendRequest()
715
716 # Save the method we use, we need it later in the response phase
717 self._method = method
718 if not url:
719 url = '/'
720 str = '%s %s %s' % (method, url, self._http_vsn_str)
721
722 self._output(str)
723
724 if self._http_vsn == 11:
725 # Issue some standard headers for better HTTP/1.1 compliance
726
727 if not skip_host:
728 # this header is issued *only* for HTTP/1.1
729 # connections. more specifically, this means it is
730 # only issued when the client uses the new
731 # HTTPConnection() class. backwards-compat clients
732 # will be using HTTP/1.0 and those clients may be
733 # issuing this header themselves. we should NOT issue
734 # it twice; some web servers (such as Apache) barf
735 # when they see two Host: headers
736
737 # If we need a non-standard port,include it in the
738 # header. If the request is going through a proxy,
739 # but the host of the actual URL, not the host of the
740 # proxy.
741
742 netloc = ''
743 if url.startswith('http'):
744 nil, netloc, nil, nil, nil = urlsplit(url)
745
746 if netloc:
747 self.putheader('Host', netloc.encode("idna"))
748 elif self.port == HTTP_PORT:
749 self.putheader('Host', self.host.encode("idna"))
750 else:
751 self.putheader('Host', "%s:%s" % (self.host.encode("idna"), self.port))
752
753 # note: we are assuming that clients will not attempt to set these
754 # headers since *this* library must deal with the
755 # consequences. this also means that when the supporting
756 # libraries are updated to recognize other forms, then this
757 # code should be changed (removed or updated).
758
759 # we only want a Content-Encoding of "identity" since we don't
760 # support encodings such as x-gzip or x-deflate.
761 if not skip_accept_encoding:
762 self.putheader('Accept-Encoding', 'identity')
763
764 # we can accept "chunked" Transfer-Encodings, but no others
765 # NOTE: no TE header implies *only* "chunked"
766 #self.putheader('TE', 'chunked')
767
768 # if TE is supplied in the header, then it must appear in a
769 # Connection header.
770 #self.putheader('Connection', 'TE')
771
772 else:
773 # For HTTP/1.0, the server will assume "not chunked"
774 pass
775
776 def putheader(self, header, value):
777 """Send a request header line to the server.
778
779 For example: h.putheader('Accept', 'text/html')
780 """
781 if self.__state != _CS_REQ_STARTED:
782 raise CannotSendHeader()
783
784 str = '%s: %s' % (header, value)
785 self._output(str)
786
787 def endheaders(self):
788 """Indicate that the last header line has been sent to the server."""
789
790 if self.__state == _CS_REQ_STARTED:
791 self.__state = _CS_REQ_SENT
792 else:
793 raise CannotSendHeader()
794
795 self._send_output()
796
797 def request(self, method, url, body=None, headers={}):
798 """Send a complete request to the server."""
799
800 try:
801 self._send_request(method, url, body, headers)
802 except socket.error, v:
803 # trap 'Broken pipe' if we're allowed to automatically reconnect
804 if v[0] != 32 or not self.auto_open:
805 raise
806 # try one more time
807 self._send_request(method, url, body, headers)
808
809 def _send_request(self, method, url, body, headers):
810 # honour explicitly requested Host: and Accept-Encoding headers
811 header_names = dict.fromkeys([k.lower() for k in headers])
812 skips = {}
813 if 'host' in header_names:
814 skips['skip_host'] = 1
815 if 'accept-encoding' in header_names:
816 skips['skip_accept_encoding'] = 1
817
818 self.putrequest(method, url, **skips)
819
820 if body and ('content-length' not in header_names):
821 self.putheader('Content-Length', str(len(body)))
822 for hdr, value in headers.iteritems():
823 self.putheader(hdr, value)
824 self.endheaders()
825
826 if body:
827 self.send(body)
828
829 def getresponse(self):
830 "Get the response from the server."
831
832 # if a prior response has been completed, then forget about it.
833 if self.__response and self.__response.isclosed():
834 self.__response = None
835
836 #
837 # if a prior response exists, then it must be completed (otherwise, we
838 # cannot read this response's header to determine the connection-close
839 # behavior)
840 #
841 # note: if a prior response existed, but was connection-close, then the
842 # socket and response were made independent of this HTTPConnection
843 # object since a new request requires that we open a whole new
844 # connection
845 #
846 # this means the prior response had one of two states:
847 # 1) will_close: this connection was reset and the prior socket and
848 # response operate independently
849 # 2) persistent: the response was retained and we await its
850 # isclosed() status to become true.
851 #
852 if self.__state != _CS_REQ_SENT or self.__response:
853 raise ResponseNotReady()
854
855 if self.debuglevel > 0:
856 response = self.response_class(self.sock, self.debuglevel,
857 strict=self.strict,
858 method=self._method)
859 else:
860 response = self.response_class(self.sock, strict=self.strict,
861 method=self._method)
862
863 response.begin()
864 assert response.will_close != _UNKNOWN
865 self.__state = _CS_IDLE
866
867 if response.will_close:
868 # this effectively passes the connection to the response
869 self.close()
870 else:
871 # remember this, so we can tell when it is complete
872 self.__response = response
873
874 return response
875
876# The next several classes are used to define FakeSocket,a socket-like
877# interface to an SSL connection.
878
879# The primary complexity comes from faking a makefile() method. The
880# standard socket makefile() implementation calls dup() on the socket
881# file descriptor. As a consequence, clients can call close() on the
882# parent socket and its makefile children in any order. The underlying
883# socket isn't closed until they are all closed.
884
885# The implementation uses reference counting to keep the socket open
886# until the last client calls close(). SharedSocket keeps track of
887# the reference counting and SharedSocketClient provides an constructor
888# and close() method that call incref() and decref() correctly.
889
890class SharedSocket:
891
892 def __init__(self, sock):
893 self.sock = sock
894 self._refcnt = 0
895
896 def incref(self):
897 self._refcnt += 1
898
899 def decref(self):
900 self._refcnt -= 1
901 assert self._refcnt >= 0
902 if self._refcnt == 0:
903 self.sock.close()
904
905 def __del__(self):
906 self.sock.close()
907
908class SharedSocketClient:
909
910 def __init__(self, shared):
911 self._closed = 0
912 self._shared = shared
913 self._shared.incref()
914 self._sock = shared.sock
915
916 def close(self):
917 if not self._closed:
918 self._shared.decref()
919 self._closed = 1
920 self._shared = None
921
922class SSLFile(SharedSocketClient):
923 """File-like object wrapping an SSL socket."""
924
925 BUFSIZE = 8192
926
927 def __init__(self, sock, ssl, bufsize=None):
928 SharedSocketClient.__init__(self, sock)
929 self._ssl = ssl
930 self._buf = ''
931 self._bufsize = bufsize or self.__class__.BUFSIZE
932
933 def _read(self):
934 buf = ''
935 # put in a loop so that we retry on transient errors
936 while True:
937 try:
938 buf = self._ssl.read(self._bufsize)
939 except socket.sslerror, err:
940 if (err[0] == socket.SSL_ERROR_WANT_READ
941 or err[0] == socket.SSL_ERROR_WANT_WRITE):
942 continue
943 if (err[0] == socket.SSL_ERROR_ZERO_RETURN
944 or err[0] == socket.SSL_ERROR_EOF):
945 break
946 raise
947 except socket.error, err:
948 if err[0] == errno.EINTR:
949 continue
950 if err[0] == errno.EBADF:
951 # XXX socket was closed?
952 break
953 raise
954 else:
955 break
956 return buf
957
958 def read(self, size=None):
959 L = [self._buf]
960 avail = len(self._buf)
961 while size is None or avail < size:
962 s = self._read()
963 if s == '':
964 break
965 L.append(s)
966 avail += len(s)
967 all = "".join(L)
968 if size is None:
969 self._buf = ''
970 return all
971 else:
972 self._buf = all[size:]
973 return all[:size]
974
975 def readline(self):
976 L = [self._buf]
977 self._buf = ''
978 while 1:
979 i = L[-1].find("\n")
980 if i >= 0:
981 break
982 s = self._read()
983 if s == '':
984 break
985 L.append(s)
986 if i == -1:
987 # loop exited because there is no more data
988 return "".join(L)
989 else:
990 all = "".join(L)
991 # XXX could do enough bookkeeping not to do a 2nd search
992 i = all.find("\n") + 1
993 line = all[:i]
994 self._buf = all[i:]
995 return line
996
997 def readlines(self, sizehint=0):
998 total = 0
999 list = []
1000 while True:
1001 line = self.readline()
1002 if not line:
1003 break
1004 list.append(line)
1005 total += len(line)
1006 if sizehint and total >= sizehint:
1007 break
1008 return list
1009
1010 def fileno(self):
1011 return self._sock.fileno()
1012
1013 def __iter__(self):
1014 return self
1015
1016 def next(self):
1017 line = self.readline()
1018 if not line:
1019 raise StopIteration
1020 return line
1021
1022class FakeSocket(SharedSocketClient):
1023
1024 class _closedsocket:
1025 def __getattr__(self, name):
1026 raise error(9, 'Bad file descriptor')
1027
1028 def __init__(self, sock, ssl):
1029 sock = SharedSocket(sock)
1030 SharedSocketClient.__init__(self, sock)
1031 self._ssl = ssl
1032
1033 def close(self):
1034 SharedSocketClient.close(self)
1035 self._sock = self.__class__._closedsocket()
1036
1037 def makefile(self, mode, bufsize=None):
1038 if mode != 'r' and mode != 'rb':
1039 raise UnimplementedFileMode()
1040 return SSLFile(self._shared, self._ssl, bufsize)
1041
1042 def send(self, stuff, flags = 0):
1043 return self._ssl.write(stuff)
1044
1045 sendall = send
1046
1047 def recv(self, len = 1024, flags = 0):
1048 return self._ssl.read(len)
1049
1050 def __getattr__(self, attr):
1051 return getattr(self._sock, attr)
1052
1053
1054class HTTPSConnection(HTTPConnection):
1055 "This class allows communication via SSL."
1056
1057 default_port = HTTPS_PORT
1058
1059 def __init__(self, host, port=None, key_file=None, cert_file=None,
1060 strict=None):
1061 HTTPConnection.__init__(self, host, port, strict)
1062 self.key_file = key_file
1063 self.cert_file = cert_file
1064
1065 def connect(self):
1066 "Connect to a host on a given (SSL) port."
1067
1068 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1069 sock.connect((self.host, self.port))
1070 ssl = socket.ssl(sock, self.key_file, self.cert_file)
1071 self.sock = FakeSocket(sock, ssl)
1072
1073
1074class HTTP:
1075 "Compatibility class with httplib.py from 1.5."
1076
1077 _http_vsn = 10
1078 _http_vsn_str = 'HTTP/1.0'
1079
1080 debuglevel = 0
1081
1082 _connection_class = HTTPConnection
1083
1084 def __init__(self, host='', port=None, strict=None):
1085 "Provide a default host, since the superclass requires one."
1086
1087 # some joker passed 0 explicitly, meaning default port
1088 if port == 0:
1089 port = None
1090
1091 # Note that we may pass an empty string as the host; this will throw
1092 # an error when we attempt to connect. Presumably, the client code
1093 # will call connect before then, with a proper host.
1094 self._setup(self._connection_class(host, port, strict))
1095
1096 def _setup(self, conn):
1097 self._conn = conn
1098
1099 # set up delegation to flesh out interface
1100 self.send = conn.send
1101 self.putrequest = conn.putrequest
1102 self.endheaders = conn.endheaders
1103 self.set_debuglevel = conn.set_debuglevel
1104
1105 conn._http_vsn = self._http_vsn
1106 conn._http_vsn_str = self._http_vsn_str
1107
1108 self.file = None
1109
1110 def connect(self, host=None, port=None):
1111 "Accept arguments to set the host/port, since the superclass doesn't."
1112
1113 if host is not None:
1114 self._conn._set_hostport(host, port)
1115 self._conn.connect()
1116
1117 def getfile(self):
1118 "Provide a getfile, since the superclass' does not use this concept."
1119 return self.file
1120
1121 def putheader(self, header, *values):
1122 "The superclass allows only one value argument."
1123 self._conn.putheader(header, '\r\n\t'.join(values))
1124
1125 def getreply(self):
1126 """Compat definition since superclass does not define it.
1127
1128 Returns a tuple consisting of:
1129 - server status code (e.g. '200' if all goes well)
1130 - server "reason" corresponding to status code
1131 - any RFC822 headers in the response from the server
1132 """
1133 try:
1134 response = self._conn.getresponse()
1135 except BadStatusLine, e:
1136 ### hmm. if getresponse() ever closes the socket on a bad request,
1137 ### then we are going to have problems with self.sock
1138
1139 ### should we keep this behavior? do people use it?
1140 # keep the socket open (as a file), and return it
1141 self.file = self._conn.sock.makefile('rb', 0)
1142
1143 # close our socket -- we want to restart after any protocol error
1144 self.close()
1145
1146 self.headers = None
1147 return -1, e.line, None
1148
1149 self.headers = response.msg
1150 self.file = response.fp
1151 return response.status, response.reason, response.msg
1152
1153 def close(self):
1154 self._conn.close()
1155
1156 # note that self.file == response.fp, which gets closed by the
1157 # superclass. just clear the object ref here.
1158 ### hmm. messy. if status==-1, then self.file is owned by us.
1159 ### well... we aren't explicitly closing, but losing this ref will
1160 ### do it
1161 self.file = None
1162
1163if hasattr(socket, 'ssl'):
1164 class HTTPS(HTTP):
1165 """Compatibility with 1.5 httplib interface
1166
1167 Python 1.5.2 did not have an HTTPS class, but it defined an
1168 interface for sending http requests that is also useful for
1169 https.
1170 """
1171
1172 _connection_class = HTTPSConnection
1173
1174 def __init__(self, host='', port=None, key_file=None, cert_file=None,
1175 strict=None):
1176 # provide a default host, pass the X509 cert info
1177
1178 # urf. compensate for bad input.
1179 if port == 0:
1180 port = None
1181 self._setup(self._connection_class(host, port, key_file,
1182 cert_file, strict))
1183
1184 # we never actually use these for anything, but we keep them
1185 # here for compatibility with post-1.5.2 CVS.
1186 self.key_file = key_file
1187 self.cert_file = cert_file
1188
1189
1190class HTTPException(Exception):
1191 # Subclasses that define an __init__ must call Exception.__init__
1192 # or define self.args. Otherwise, str() will fail.
1193 pass
1194
1195class NotConnected(HTTPException):
1196 pass
1197
1198class InvalidURL(HTTPException):
1199 pass
1200
1201class UnknownProtocol(HTTPException):
1202 def __init__(self, version):
1203 self.args = version,
1204 self.version = version
1205
1206class UnknownTransferEncoding(HTTPException):
1207 pass
1208
1209class UnimplementedFileMode(HTTPException):
1210 pass
1211
1212class IncompleteRead(HTTPException):
1213 def __init__(self, partial):
1214 self.args = partial,
1215 self.partial = partial
1216
1217class ImproperConnectionState(HTTPException):
1218 pass
1219
1220class CannotSendRequest(ImproperConnectionState):
1221 pass
1222
1223class CannotSendHeader(ImproperConnectionState):
1224 pass
1225
1226class ResponseNotReady(ImproperConnectionState):
1227 pass
1228
1229class BadStatusLine(HTTPException):
1230 def __init__(self, line):
1231 self.args = line,
1232 self.line = line
1233
1234# for backwards compatibility
1235error = HTTPException
1236
1237class LineAndFileWrapper:
1238 """A limited file-like object for HTTP/0.9 responses."""
1239
1240 # The status-line parsing code calls readline(), which normally
1241 # get the HTTP status line. For a 0.9 response, however, this is
1242 # actually the first line of the body! Clients need to get a
1243 # readable file object that contains that line.
1244
1245 def __init__(self, line, file):
1246 self._line = line
1247 self._file = file
1248 self._line_consumed = 0
1249 self._line_offset = 0
1250 self._line_left = len(line)
1251
1252 def __getattr__(self, attr):
1253 return getattr(self._file, attr)
1254
1255 def _done(self):
1256 # called when the last byte is read from the line. After the
1257 # call, all read methods are delegated to the underlying file
1258 # object.
1259 self._line_consumed = 1
1260 self.read = self._file.read
1261 self.readline = self._file.readline
1262 self.readlines = self._file.readlines
1263
1264 def read(self, amt=None):
1265 if self._line_consumed:
1266 return self._file.read(amt)
1267 assert self._line_left
1268 if amt is None or amt > self._line_left:
1269 s = self._line[self._line_offset:]
1270 self._done()
1271 if amt is None:
1272 return s + self._file.read()
1273 else:
1274 return s + self._file.read(amt - len(s))
1275 else:
1276 assert amt <= self._line_left
1277 i = self._line_offset
1278 j = i + amt
1279 s = self._line[i:j]
1280 self._line_offset = j
1281 self._line_left -= amt
1282 if self._line_left == 0:
1283 self._done()
1284 return s
1285
1286 def readline(self):
1287 if self._line_consumed:
1288 return self._file.readline()
1289 assert self._line_left
1290 s = self._line[self._line_offset:]
1291 self._done()
1292 return s
1293
1294 def readlines(self, size=None):
1295 if self._line_consumed:
1296 return self._file.readlines(size)
1297 assert self._line_left
1298 L = [self._line[self._line_offset:]]
1299 self._done()
1300 if size is None:
1301 return L + self._file.readlines()
1302 else:
1303 return L + self._file.readlines(size)
1304
1305def test():
1306 """Test this module.
1307
1308 A hodge podge of tests collected here, because they have too many
1309 external dependencies for the regular test suite.
1310 """
1311
1312 import sys
1313 import getopt
1314 opts, args = getopt.getopt(sys.argv[1:], 'd')
1315 dl = 0
1316 for o, a in opts:
1317 if o == '-d': dl = dl + 1
1318 host = 'www.python.org'
1319 selector = '/'
1320 if args[0:]: host = args[0]
1321 if args[1:]: selector = args[1]
1322 h = HTTP()
1323 h.set_debuglevel(dl)
1324 h.connect(host)
1325 h.putrequest('GET', selector)
1326 h.endheaders()
1327 status, reason, headers = h.getreply()
1328 print 'status =', status
1329 print 'reason =', reason
1330 print "read", len(h.getfile().read())
1331 print
1332 if headers:
1333 for header in headers.headers: print header.strip()
1334 print
1335
1336 # minimal test that code to extract host from url works
1337 class HTTP11(HTTP):
1338 _http_vsn = 11
1339 _http_vsn_str = 'HTTP/1.1'
1340
1341 h = HTTP11('www.python.org')
1342 h.putrequest('GET', 'http://www.python.org/~jeremy/')
1343 h.endheaders()
1344 h.getreply()
1345 h.close()
1346
1347 if hasattr(socket, 'ssl'):
1348
1349 for host, selector in (('sourceforge.net', '/projects/python'),
1350 ):
1351 print "https://%s%s" % (host, selector)
1352 hs = HTTPS()
1353 hs.set_debuglevel(dl)
1354 hs.connect(host)
1355 hs.putrequest('GET', selector)
1356 hs.endheaders()
1357 status, reason, headers = hs.getreply()
1358 print 'status =', status
1359 print 'reason =', reason
1360 print "read", len(hs.getfile().read())
1361 print
1362 if headers:
1363 for header in headers.headers: print header.strip()
1364 print
1365
1366if __name__ == '__main__':
1367 test()