(py-electric-colon): use a save-excursion instead of a progn in
[python/dscho.git] / Lib / httplib.py
blob362b38d59708a2729ad240971d80043c8645b069
1 # HTTP client class
3 # See the following document for a tentative protocol description:
4 # Hypertext Transfer Protocol (HTTP) Tim Berners-Lee, CERN
5 # Internet Draft 5 Nov 1993
6 # draft-ietf-iiir-http-00.txt Expires 5 May 1994
8 # Example:
10 # >>> from httplib import HTTP
11 # >>> h = HTTP('www.cwi.nl')
12 # >>> h.putreqest('GET', '/index.html')
13 # >>> h.putheader('Accept', 'text/html')
14 # >>> h.putheader('Accept', 'text/plain')
15 # >>> errcode, errmsg, headers = h.getreply()
16 # >>> if errcode == 200:
17 # ... f = h.getfile()
18 # ... print f.read() # Print the raw HTML
19 # ...
20 # <TITLE>Home Page of CWI, Amsterdam</TITLE>
21 # [...many more lines...]
22 # >>>
24 # Note that an HTTP object is used for a single request -- to issue a
25 # second request to the same server, you create a new HTTP object.
26 # (This is in accordance with the protocol, which uses a new TCP
27 # connection for each request.)
30 import os
31 import socket
32 import string
33 import regex
34 import regsub
35 import rfc822
37 HTTP_VERSION = 'HTTP/1.0'
38 HTTP_PORT = 80
40 replypat = regsub.gsub('\\.', '\\\\.', HTTP_VERSION) + \
41 '[ \t]+\([0-9][0-9][0-9]\)\(.*\)'
42 replyprog = regex.compile(replypat)
44 class HTTP:
46 def __init__(self, host = '', port = 0):
47 self.debuglevel = 0
48 if host: self.connect(host, port)
50 def set_debuglevel(self, debuglevel):
51 self.debuglevel = debuglevel
53 def connect(self, host, port = 0):
54 if not port:
55 i = string.find(host, ':')
56 if i >= 0:
57 host, port = host[:i], host[i+1:]
58 try: port = string.atoi(port)
59 except string.atoi_error: pass
60 if not port: port = HTTP_PORT
61 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
62 if self.debuglevel > 0: print 'connect:', (host, port)
63 self.sock.connect(host, port)
65 def send(self, str):
66 if self.debuglevel > 0: print 'send:', `str`
67 self.sock.send(str)
69 def putrequest(self, request, selector):
70 str = '%s %s %s\r\n' % (request, selector, HTTP_VERSION)
71 self.send(str)
73 def putheader(self, header, *args):
74 str = '%s: %s\r\n' % (header, string.joinfields(args,'\r\n\t'))
75 self.send(str)
77 def endheaders(self):
78 self.send('\r\n')
80 def endrequest(self):
81 if self.debuglevel > 0: print 'shutdown: 1'
82 self.sock.shutdown(1)
84 def getreply(self):
85 self.endrequest()
86 self.file = self.sock.makefile('r')
87 line = self.file.readline()
88 if self.debuglevel > 0: print 'reply:', `line`
89 if replyprog.match(line) < 0:
90 self.headers = None
91 return -1, line, self.headers
92 errcode, errmsg = replyprog.group(1, 2)
93 errcode = string.atoi(errcode)
94 errmsg = string.strip(errmsg)
95 self.headers = rfc822.Message(self.file)
96 return errcode, errmsg, self.headers
98 def getfile(self):
99 return self.file
102 def test():
103 import sys
104 import getopt
105 opts, args = getopt.getopt(sys.argv[1:], 'd')
106 dl = 0
107 for o, a in opts:
108 if o == '-d': dl = dl + 1
109 host = 'www.cwi.nl:80'
110 selector = '/index.html'
111 if args[0:]: host = args[0]
112 if args[1:]: selector = args[1]
113 h = HTTP()
114 h.set_debuglevel(dl)
115 h.connect(host)
116 h.putrequest('GET', selector)
117 errcode, errmsg, headers = h.getreply()
118 print 'errcode =', errcode
119 print 'headers =', headers
120 print 'errmsg =', errmsg
121 if headers:
122 for header in headers.headers: print string.strip(header)
123 print h.getfile().read()
125 if __name__ == '__main__':
126 test()