Vega strike Python Modules doc  0.5.1
Documentation of the " Modules " folder of Vega strike
 All Data Structures Namespaces Files Functions Variables
httplib.py
Go to the documentation of this file.
1 """HTTP/1.1 client library
2 
3 <intro stuff goes here>
4 <other stuff, too>
5 
6 HTTPConnection go through a number of "states", which defines when a client
7 may legally make another request or fetch the response for a particular
8 request. 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 
42 This 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 
48 Note: 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 
59 Logical State __state __response
60 ------------- ------- ----------
61 Idle _CS_IDLE None
62 Request-started _CS_REQ_STARTED None
63 Request-sent _CS_REQ_SENT None
64 Unread-response _CS_IDLE <response_class>
65 Req-started-unread-response _CS_REQ_STARTED <response_class>
66 Req-sent-unread-response _CS_REQ_SENT <response_class>
67 """
68 
69 import errno
70 import mimetools
71 import socket
72 from urlparse import urlsplit
73 
74 try:
75  from cStringIO import StringIO
76 except ImportError:
77  from StringIO import StringIO
78 
79 __all__ = ["HTTP", "HTTPResponse", "HTTPConnection", "HTTPSConnection",
80  "HTTPException", "NotConnected", "UnknownProtocol",
81  "UnknownTransferEncoding", "IllegalKeywordArgument",
82  "UnimplementedFileMode", "IncompleteRead",
83  "ImproperConnectionState", "CannotSendRequest", "CannotSendHeader",
84  "ResponseNotReady", "BadStatusLine", "error"]
85 
86 HTTP_PORT = 80
87 HTTPS_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 
98  def __init__(self, sock, debuglevel=0):
99  self.fp = sock.makefile('rb', 0)
100  self.debuglevel = debuglevel
101 
102  self.msg = None
103 
104  # from the Status-Line of the response
105  self.version = _UNKNOWN # HTTP-Version
106  self.status = _UNKNOWN # Status-Code
107  self.reason = _UNKNOWN # Reason-Phrase
108 
109  self.chunked = _UNKNOWN # is "chunked" being used?
110  self.chunk_left = _UNKNOWN # bytes left to read in current chunk
111  self.length = _UNKNOWN # number of bytes left in response
112  self.will_close = _UNKNOWN # conn will close at end of response
113 
114  def begin(self):
115  if self.msg is not None:
116  # we've already started reading the response
117  return
118 
119  line = self.fp.readline()
120  if self.debuglevel > 0:
121  print "reply:", repr(line)
122  try:
123  [version, status, reason] = line.split(None, 2)
124  except ValueError:
125  try:
126  [version, status] = line.split(None, 1)
127  reason = ""
128  except ValueError:
129  version = "HTTP/0.9"
130  status = "200"
131  reason = ""
132  if version[:5] != 'HTTP/':
133  self.close()
134  raise BadStatusLine(line)
135 
136  # The status code is a three-digit number
137  try:
138  self.status = status = int(status)
139  if status < 100 or status > 999:
140  raise BadStatusLine(line)
141  except ValueError:
142  raise BadStatusLine(line)
143  self.reason = reason.strip()
144 
145  if version == 'HTTP/1.0':
146  self.version = 10
147  elif version.startswith('HTTP/1.'):
148  self.version = 11 # use HTTP/1.1 code for HTTP/1.x where x>=1
149  elif version == 'HTTP/0.9':
150  self.version = 9
151  else:
152  raise UnknownProtocol(version)
153 
154  if self.version == 9:
155  self.msg = mimetools.Message(StringIO())
156  return
157 
158  self.msg = mimetools.Message(self.fp, 0)
159  if self.debuglevel > 0:
160  for hdr in self.msg.headers:
161  print "header:", hdr,
162 
163  # don't let the msg keep an fp
164  self.msg.fp = None
165 
166  # are we using the chunked-style of transfer encoding?
167  tr_enc = self.msg.getheader('transfer-encoding')
168  if tr_enc:
169  if tr_enc.lower() != 'chunked':
171  self.chunked = 1
172  self.chunk_left = None
173  else:
174  self.chunked = 0
175 
176  # will the connection close at the end of the response?
177  conn = self.msg.getheader('connection')
178  if conn:
179  conn = conn.lower()
180  # a "Connection: close" will always close the connection. if we
181  # don't see that and this is not HTTP/1.1, then the connection will
182  # close unless we see a Keep-Alive header.
183  self.will_close = conn.find('close') != -1 or \
184  ( self.version != 11 and \
185  not self.msg.getheader('keep-alive') )
186  else:
187  # for HTTP/1.1, the connection will always remain open
188  # otherwise, it will remain open IFF we see a Keep-Alive header
189  self.will_close = self.version != 11 and \
190  not self.msg.getheader('keep-alive')
191 
192  # do we have a Content-Length?
193  # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
194  length = self.msg.getheader('content-length')
195  if length and not self.chunked:
196  try:
197  self.length = int(length)
198  except ValueError:
199  self.length = None
200  else:
201  self.length = None
202 
203  # does the body have a fixed length? (of zero)
204  if (status == 204 or # No Content
205  status == 304 or # Not Modified
206  100 <= status < 200): # 1xx codes
207  self.length = 0
208 
209  # if the connection remains open, and we aren't using chunked, and
210  # a content-length was not provided, then assume that the connection
211  # WILL close.
212  if not self.will_close and \
213  not self.chunked and \
214  self.length is None:
215  self.will_close = 1
216 
217  def close(self):
218  if self.fp:
219  self.fp.close()
220  self.fp = None
221 
222  def isclosed(self):
223  # NOTE: it is possible that we will not ever call self.close(). This
224  # case occurs when will_close is TRUE, length is None, and we
225  # read up to the last byte, but NOT past it.
226  #
227  # IMPLIES: if will_close is FALSE, then self.close() will ALWAYS be
228  # called, meaning self.isclosed() is meaningful.
229  return self.fp is None
230 
231  def read(self, amt=None):
232  if self.fp is None:
233  return ''
234 
235  if self.chunked:
236  chunk_left = self.chunk_left
237  value = ''
238  while 1:
239  if chunk_left is None:
240  line = self.fp.readline()
241  i = line.find(';')
242  if i >= 0:
243  line = line[:i] # strip chunk-extensions
244  chunk_left = int(line, 16)
245  if chunk_left == 0:
246  break
247  if amt is None:
248  value = value + self._safe_read(chunk_left)
249  elif amt < chunk_left:
250  value = value + self._safe_read(amt)
251  self.chunk_left = chunk_left - amt
252  return value
253  elif amt == chunk_left:
254  value = value + self._safe_read(amt)
255  self._safe_read(2) # toss the CRLF at the end of the chunk
256  self.chunk_left = None
257  return value
258  else:
259  value = value + self._safe_read(chunk_left)
260  amt = amt - chunk_left
261 
262  # we read the whole chunk, get another
263  self._safe_read(2) # toss the CRLF at the end of the chunk
264  chunk_left = None
265 
266  # read and discard trailer up to the CRLF terminator
267  ### note: we shouldn't have any trailers!
268  while 1:
269  line = self.fp.readline()
270  if line == '\r\n':
271  break
272 
273  # we read everything; close the "file"
274  self.close()
275 
276  return value
277 
278  elif amt is None:
279  # unbounded read
280  if self.will_close:
281  s = self.fp.read()
282  else:
283  s = self._safe_read(self.length)
284  self.close() # we read everything
285  return s
286 
287  if self.length is not None:
288  if amt > self.length:
289  # clip the read to the "end of response"
290  amt = self.length
291  self.length = self.length - amt
292 
293  # we do not use _safe_read() here because this may be a .will_close
294  # connection, and the user is reading more bytes than will be provided
295  # (for example, reading in 1k chunks)
296  s = self.fp.read(amt)
297 
298  return s
299 
300  def _safe_read(self, amt):
301  """Read the number of bytes requested, compensating for partial reads.
302 
303  Normally, we have a blocking socket, but a read() can be interrupted
304  by a signal (resulting in a partial read).
305 
306  Note that we cannot distinguish between EOF and an interrupt when zero
307  bytes have been read. IncompleteRead() will be raised in this
308  situation.
309 
310  This function should be used when <amt> bytes "should" be present for
311  reading. If the bytes are truly not available (due to EOF), then the
312  IncompleteRead exception can be used to detect the problem.
313  """
314  s = ''
315  while amt > 0:
316  chunk = self.fp.read(amt)
317  if not chunk:
318  raise IncompleteRead(s)
319  s = s + chunk
320  amt = amt - len(chunk)
321  return s
322 
323  def getheader(self, name, default=None):
324  if self.msg is None:
325  raise ResponseNotReady()
326  return self.msg.getheader(name, default)
327 
328 
330 
331  _http_vsn = 11
332  _http_vsn_str = 'HTTP/1.1'
333 
334  response_class = HTTPResponse
335  default_port = HTTP_PORT
336  auto_open = 1
337  debuglevel = 0
338 
339  def __init__(self, host, port=None):
340  self.sock = None
341  self.__response = None
342  self.__state = _CS_IDLE
343 
344  self._set_hostport(host, port)
345 
346  def _set_hostport(self, host, port):
347  if port is None:
348  i = host.find(':')
349  if i >= 0:
350  port = int(host[i+1:])
351  host = host[:i]
352  else:
353  port = self.default_port
354  self.host = host
355  self.port = port
356 
357  def set_debuglevel(self, level):
358  self.debuglevel = level
359 
360  def connect(self):
361  """Connect to the host and port specified in __init__."""
362  msg = "getaddrinfo returns an empty list"
363  for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
364  af, socktype, proto, canonname, sa = res
365  try:
366  self.sock = socket.socket(af, socktype, proto)
367  if self.debuglevel > 0:
368  print "connect: (%s, %s)" % (self.host, self.port)
369  self.sock.connect(sa)
370  except socket.error, msg:
371  if self.debuglevel > 0:
372  print 'connect fail:', (self.host, self.port)
373  if self.sock:
374  self.sock.close()
375  self.sock = None
376  continue
377  break
378  if not self.sock:
379  raise socket.error, msg
380 
381  def close(self):
382  """Close the connection to the HTTP server."""
383  if self.sock:
384  self.sock.close() # close it manually... there may be other refs
385  self.sock = None
386  if self.__response:
387  self.__response.close()
388  self.__response = None
389  self.__state = _CS_IDLE
390 
391  def send(self, str):
392  """Send `str' to the server."""
393  if self.sock is None:
394  if self.auto_open:
395  self.connect()
396  else:
397  raise NotConnected()
398 
399  # send the data to the server. if we get a broken pipe, then close
400  # the socket. we want to reconnect when somebody tries to send again.
401  #
402  # NOTE: we DO propagate the error, though, because we cannot simply
403  # ignore the error... the caller will know if they can retry.
404  if self.debuglevel > 0:
405  print "send:", repr(str)
406  try:
407  self.sock.sendall(str)
408  except socket.error, v:
409  if v[0] == 32: # Broken pipe
410  self.close()
411  raise
412 
413  def putrequest(self, method, url, skip_host=0):
414  """Send a request to the server.
415 
416  `method' specifies an HTTP request method, e.g. 'GET'.
417  `url' specifies the object being requested, e.g. '/index.html'.
418  """
419 
420  # check if a prior response has been completed
421  if self.__response and self.__response.isclosed():
422  self.__response = None
423 
424  #
425  # in certain cases, we cannot issue another request on this connection.
426  # this occurs when:
427  # 1) we are in the process of sending a request. (_CS_REQ_STARTED)
428  # 2) a response to a previous request has signalled that it is going
429  # to close the connection upon completion.
430  # 3) the headers for the previous response have not been read, thus
431  # we cannot determine whether point (2) is true. (_CS_REQ_SENT)
432  #
433  # if there is no prior response, then we can request at will.
434  #
435  # if point (2) is true, then we will have passed the socket to the
436  # response (effectively meaning, "there is no prior response"), and
437  # will open a new one when a new request is made.
438  #
439  # Note: if a prior response exists, then we *can* start a new request.
440  # We are not allowed to begin fetching the response to this new
441  # request, however, until that prior response is complete.
442  #
443  if self.__state == _CS_IDLE:
444  self.__state = _CS_REQ_STARTED
445  else:
446  raise CannotSendRequest()
447 
448  if not url:
449  url = '/'
450  str = '%s %s %s\r\n' % (method, url, self._http_vsn_str)
451 
452  try:
453  self.send(str)
454  except socket.error, v:
455  # trap 'Broken pipe' if we're allowed to automatically reconnect
456  if v[0] != 32 or not self.auto_open:
457  raise
458  # try one more time (the socket was closed; this will reopen)
459  self.send(str)
460 
461  if self._http_vsn == 11:
462  # Issue some standard headers for better HTTP/1.1 compliance
463 
464  if not skip_host:
465  # this header is issued *only* for HTTP/1.1
466  # connections. more specifically, this means it is
467  # only issued when the client uses the new
468  # HTTPConnection() class. backwards-compat clients
469  # will be using HTTP/1.0 and those clients may be
470  # issuing this header themselves. we should NOT issue
471  # it twice; some web servers (such as Apache) barf
472  # when they see two Host: headers
473 
474  # If we need a non-standard port,include it in the
475  # header. If the request is going through a proxy,
476  # but the host of the actual URL, not the host of the
477  # proxy.
478 
479  netloc = ''
480  if url.startswith('http'):
481  nil, netloc, nil, nil, nil = urlsplit(url)
482 
483  if netloc:
484  self.putheader('Host', netloc)
485  elif self.port == HTTP_PORT:
486  self.putheader('Host', self.host)
487  else:
488  self.putheader('Host', "%s:%s" % (self.host, self.port))
489 
490  # note: we are assuming that clients will not attempt to set these
491  # headers since *this* library must deal with the
492  # consequences. this also means that when the supporting
493  # libraries are updated to recognize other forms, then this
494  # code should be changed (removed or updated).
495 
496  # we only want a Content-Encoding of "identity" since we don't
497  # support encodings such as x-gzip or x-deflate.
498  self.putheader('Accept-Encoding', 'identity')
499 
500  # we can accept "chunked" Transfer-Encodings, but no others
501  # NOTE: no TE header implies *only* "chunked"
502  #self.putheader('TE', 'chunked')
503 
504  # if TE is supplied in the header, then it must appear in a
505  # Connection header.
506  #self.putheader('Connection', 'TE')
507 
508  else:
509  # For HTTP/1.0, the server will assume "not chunked"
510  pass
511 
512  def putheader(self, header, value):
513  """Send a request header line to the server.
514 
515  For example: h.putheader('Accept', 'text/html')
516  """
517  if self.__state != _CS_REQ_STARTED:
518  raise CannotSendHeader()
519 
520  str = '%s: %s\r\n' % (header, value)
521  self.send(str)
522 
523  def endheaders(self):
524  """Indicate that the last header line has been sent to the server."""
525 
526  if self.__state == _CS_REQ_STARTED:
527  self.__state = _CS_REQ_SENT
528  else:
529  raise CannotSendHeader()
530 
531  self.send('\r\n')
532 
533  def request(self, method, url, body=None, headers={}):
534  """Send a complete request to the server."""
535 
536  try:
537  self._send_request(method, url, body, headers)
538  except socket.error, v:
539  # trap 'Broken pipe' if we're allowed to automatically reconnect
540  if v[0] != 32 or not self.auto_open:
541  raise
542  # try one more time
543  self._send_request(method, url, body, headers)
544 
545  def _send_request(self, method, url, body, headers):
546  # If headers already contains a host header, then define the
547  # optional skip_host argument to putrequest(). The check is
548  # harder because field names are case insensitive.
549  if (headers.has_key('Host')
550  or [k for k in headers.iterkeys() if k.lower() == "host"]):
551  self.putrequest(method, url, skip_host=1)
552  else:
553  self.putrequest(method, url)
554 
555  if body:
556  self.putheader('Content-Length', str(len(body)))
557  for hdr, value in headers.items():
558  self.putheader(hdr, value)
559  self.endheaders()
560 
561  if body:
562  self.send(body)
563 
564  def getresponse(self):
565  "Get the response from the server."
566 
567  # check if a prior response has been completed
568  if self.__response and self.__response.isclosed():
569  self.__response = None
570 
571  #
572  # if a prior response exists, then it must be completed (otherwise, we
573  # cannot read this response's header to determine the connection-close
574  # behavior)
575  #
576  # note: if a prior response existed, but was connection-close, then the
577  # socket and response were made independent of this HTTPConnection
578  # object since a new request requires that we open a whole new
579  # connection
580  #
581  # this means the prior response had one of two states:
582  # 1) will_close: this connection was reset and the prior socket and
583  # response operate independently
584  # 2) persistent: the response was retained and we await its
585  # isclosed() status to become true.
586  #
587  if self.__state != _CS_REQ_SENT or self.__response:
588  raise ResponseNotReady()
589 
590  if self.debuglevel > 0:
591  response = self.response_class(self.sock, self.debuglevel)
592  else:
593  response = self.response_class(self.sock)
594 
595  response.begin()
596  self.__state = _CS_IDLE
597 
598  if response.will_close:
599  # this effectively passes the connection to the response
600  self.close()
601  else:
602  # remember this, so we can tell when it is complete
603  self.__response = response
604 
605  return response
606 
607 
609  def __init__(self, sock, ssl):
610  self.__sock = sock
611  self.__ssl = ssl
612 
613  def makefile(self, mode, bufsize=None):
614  """Return a readable file-like object with data from socket.
615 
616  This method offers only partial support for the makefile
617  interface of a real socket. It only supports modes 'r' and
618  'rb' and the bufsize argument is ignored.
619 
620  The returned object contains *all* of the file data
621  """
622  if mode != 'r' and mode != 'rb':
623  raise UnimplementedFileMode()
624 
625  msgbuf = []
626  while 1:
627  try:
628  buf = self.__ssl.read()
629  except socket.sslerror, err:
630  if (err[0] == socket.SSL_ERROR_WANT_READ
631  or err[0] == socket.SSL_ERROR_WANT_WRITE
632  or 0):
633  continue
634  if err[0] == socket.SSL_ERROR_ZERO_RETURN:
635  break
636  raise
637  except socket.error, err:
638  if err[0] == errno.EINTR:
639  continue
640  raise
641  if buf == '':
642  break
643  msgbuf.append(buf)
644  return StringIO("".join(msgbuf))
645 
646  def send(self, stuff, flags = 0):
647  return self.__ssl.write(stuff)
648 
649  def sendall(self, stuff, flags = 0):
650  return self.__ssl.write(stuff)
651 
652  def recv(self, len = 1024, flags = 0):
653  return self.__ssl.read(len)
654 
655  def __getattr__(self, attr):
656  return getattr(self.__sock, attr)
657 
658 
659 class HTTPSConnection(HTTPConnection):
660  "This class allows communication via SSL."
661 
662  default_port = HTTPS_PORT
663 
664  def __init__(self, host, port=None, **x509):
665  keys = x509.keys()
666  try:
667  keys.remove('key_file')
668  except ValueError:
669  pass
670  try:
671  keys.remove('cert_file')
672  except ValueError:
673  pass
674  if keys:
675  raise IllegalKeywordArgument()
676  HTTPConnection.__init__(self, host, port)
677  self.key_file = x509.get('key_file')
678  self.cert_file = x509.get('cert_file')
679 
680  def connect(self):
681  "Connect to a host on a given (SSL) port."
682 
683  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
684  sock.connect((self.host, self.port))
685  realsock = sock
686  if hasattr(sock, "_sock"):
687  realsock = sock._sock
688  ssl = socket.ssl(realsock, self.key_file, self.cert_file)
689  self.sock = FakeSocket(sock, ssl)
690 
691 
692 class HTTP:
693  "Compatibility class with httplib.py from 1.5."
694 
695  _http_vsn = 10
696  _http_vsn_str = 'HTTP/1.0'
697 
698  debuglevel = 0
699 
700  _connection_class = HTTPConnection
701 
702  def __init__(self, host='', port=None):
703  "Provide a default host, since the superclass requires one."
704 
705  # some joker passed 0 explicitly, meaning default port
706  if port == 0:
707  port = None
708 
709  # Note that we may pass an empty string as the host; this will throw
710  # an error when we attempt to connect. Presumably, the client code
711  # will call connect before then, with a proper host.
712  self._setup(self._connection_class(host, port))
713 
714  def _setup(self, conn):
715  self._conn = conn
716 
717  # set up delegation to flesh out interface
718  self.send = conn.send
719  self.putrequest = conn.putrequest
720  self.endheaders = conn.endheaders
721  self.set_debuglevel = conn.set_debuglevel
722 
723  conn._http_vsn = self._http_vsn
724  conn._http_vsn_str = self._http_vsn_str
725 
726  self.file = None
727 
728  def connect(self, host=None, port=None):
729  "Accept arguments to set the host/port, since the superclass doesn't."
730 
731  if host is not None:
732  self._conn._set_hostport(host, port)
733  self._conn.connect()
734 
735  def getfile(self):
736  "Provide a getfile, since the superclass' does not use this concept."
737  return self.file
738 
739  def putheader(self, header, *values):
740  "The superclass allows only one value argument."
741  self._conn.putheader(header, '\r\n\t'.join(values))
742 
743  def getreply(self):
744  """Compat definition since superclass does not define it.
745 
746  Returns a tuple consisting of:
747  - server status code (e.g. '200' if all goes well)
748  - server "reason" corresponding to status code
749  - any RFC822 headers in the response from the server
750  """
751  try:
752  response = self._conn.getresponse()
753  except BadStatusLine, e:
754  ### hmm. if getresponse() ever closes the socket on a bad request,
755  ### then we are going to have problems with self.sock
756 
757  ### should we keep this behavior? do people use it?
758  # keep the socket open (as a file), and return it
759  self.file = self._conn.sock.makefile('rb', 0)
760 
761  # close our socket -- we want to restart after any protocol error
762  self.close()
763 
764  self.headers = None
765  return -1, e.line, None
766 
767  self.headers = response.msg
768  self.file = response.fp
769  return response.status, response.reason, response.msg
770 
771  def close(self):
772  self._conn.close()
773 
774  # note that self.file == response.fp, which gets closed by the
775  # superclass. just clear the object ref here.
776  ### hmm. messy. if status==-1, then self.file is owned by us.
777  ### well... we aren't explicitly closing, but losing this ref will
778  ### do it
779  self.file = None
780 
781 if hasattr(socket, 'ssl'):
782  class HTTPS(HTTP):
783  """Compatibility with 1.5 httplib interface
784 
785  Python 1.5.2 did not have an HTTPS class, but it defined an
786  interface for sending http requests that is also useful for
787  https.
788  """
789 
790  _connection_class = HTTPSConnection
791 
792  def __init__(self, host='', port=None, **x509):
793  # provide a default host, pass the X509 cert info
794 
795  # urf. compensate for bad input.
796  if port == 0:
797  port = None
798  self._setup(self._connection_class(host, port, **x509))
799 
800  # we never actually use these for anything, but we keep them
801  # here for compatibility with post-1.5.2 CVS.
802  self.key_file = x509.get('key_file')
803  self.cert_file = x509.get('cert_file')
804 
805 
806 class HTTPException(Exception):
807  pass
808 
809 class NotConnected(HTTPException):
810  pass
811 
812 class UnknownProtocol(HTTPException):
813  def __init__(self, version):
814  self.version = version
815 
816 class UnknownTransferEncoding(HTTPException):
817  pass
818 
819 class IllegalKeywordArgument(HTTPException):
820  pass
821 
822 class UnimplementedFileMode(HTTPException):
823  pass
824 
825 class IncompleteRead(HTTPException):
826  def __init__(self, partial):
827  self.partial = partial
828 
829 class ImproperConnectionState(HTTPException):
830  pass
831 
832 class CannotSendRequest(ImproperConnectionState):
833  pass
834 
835 class CannotSendHeader(ImproperConnectionState):
836  pass
837 
838 class ResponseNotReady(ImproperConnectionState):
839  pass
840 
841 class BadStatusLine(HTTPException):
842  def __init__(self, line):
843  self.line = line
844 
845 # for backwards compatibility
846 error = HTTPException
847 
848 
849 #
850 # snarfed from httplib.py for now...
851 #
852 def test():
853  """Test this module.
854 
855  The test consists of retrieving and displaying the Python
856  home page, along with the error code and error string returned
857  by the www.python.org server.
858  """
859 
860  import sys
861  import getopt
862  opts, args = getopt.getopt(sys.argv[1:], 'd')
863  dl = 0
864  for o, a in opts:
865  if o == '-d': dl = dl + 1
866  host = 'www.python.org'
867  selector = '/'
868  if args[0:]: host = args[0]
869  if args[1:]: selector = args[1]
870  h = HTTP()
871  h.set_debuglevel(dl)
872  h.connect(host)
873  h.putrequest('GET', selector)
874  h.endheaders()
875  status, reason, headers = h.getreply()
876  print 'status =', status
877  print 'reason =', reason
878  print
879  if headers:
880  for header in headers.headers: print header.strip()
881  print
882  print h.getfile().read()
883 
884  # minimal test that code to extract host from url works
885  class HTTP11(HTTP):
886  _http_vsn = 11
887  _http_vsn_str = 'HTTP/1.1'
888 
889  h = HTTP11('www.python.org')
890  h.putrequest('GET', 'http://www.python.org/~jeremy/')
891  h.endheaders()
892  h.getreply()
893  h.close()
894 
895  if hasattr(socket, 'ssl'):
896  host = 'sourceforge.net'
897  selector = '/projects/python'
898  hs = HTTPS()
899  hs.connect(host)
900  hs.putrequest('GET', selector)
901  hs.endheaders()
902  status, reason, headers = hs.getreply()
903  print 'status =', status
904  print 'reason =', reason
905  print
906  if headers:
907  for header in headers.headers: print header.strip()
908  print
909  print hs.getfile().read()
910 
911 
912 if __name__ == '__main__':
913  test()