blob: fa7d2b7b78ae1169407187171f4901c6d2833131 [file] [log] [blame]
Guido van Rossum23acc951994-02-21 16:36:04 +00001# HTTP client class
2#
Guido van Rossum928fced1995-09-30 16:50:46 +00003# See the following URL for a description of the HTTP/1.0 protocol:
4# http://www.w3.org/hypertext/WWW/Protocols/
5# (I actually implemented it from a much earlier draft.)
Guido van Rossum23acc951994-02-21 16:36:04 +00006#
7# Example:
8#
9# >>> from httplib import HTTP
Guido van Rossum928fced1995-09-30 16:50:46 +000010# >>> h = HTTP('www.python.org')
11# >>> h.putrequest('GET', '/index.html')
Guido van Rossum23acc951994-02-21 16:36:04 +000012# >>> h.putheader('Accept', 'text/html')
13# >>> h.putheader('Accept', 'text/plain')
Guido van Rossum4cdcef71995-06-22 18:48:48 +000014# >>> h.endheaders()
Guido van Rossum23acc951994-02-21 16:36:04 +000015# >>> errcode, errmsg, headers = h.getreply()
16# >>> if errcode == 200:
17# ... f = h.getfile()
18# ... print f.read() # Print the raw HTML
19# ...
Guido van Rossum928fced1995-09-30 16:50:46 +000020# <HEAD>
21# <TITLE>Python Language Home Page</TITLE>
Guido van Rossum23acc951994-02-21 16:36:04 +000022# [...many more lines...]
23# >>>
24#
25# Note that an HTTP object is used for a single request -- to issue a
26# second request to the same server, you create a new HTTP object.
27# (This is in accordance with the protocol, which uses a new TCP
28# connection for each request.)
29
30
Guido van Rossum23acc951994-02-21 16:36:04 +000031import socket
32import string
Guido van Rossum65ab98c1995-08-07 20:13:02 +000033import mimetools
Guido van Rossum23acc951994-02-21 16:36:04 +000034
35HTTP_VERSION = 'HTTP/1.0'
36HTTP_PORT = 80
37
Guido van Rossum23acc951994-02-21 16:36:04 +000038class HTTP:
39
Guido van Rossum2922c6d1994-05-06 14:28:19 +000040 def __init__(self, host = '', port = 0):
Guido van Rossum23acc951994-02-21 16:36:04 +000041 self.debuglevel = 0
Guido van Rossum65ab98c1995-08-07 20:13:02 +000042 self.file = None
Guido van Rossum2922c6d1994-05-06 14:28:19 +000043 if host: self.connect(host, port)
Guido van Rossum23acc951994-02-21 16:36:04 +000044
45 def set_debuglevel(self, debuglevel):
46 self.debuglevel = debuglevel
47
Guido van Rossum2922c6d1994-05-06 14:28:19 +000048 def connect(self, host, port = 0):
49 if not port:
Guido van Rossum23acc951994-02-21 16:36:04 +000050 i = string.find(host, ':')
51 if i >= 0:
52 host, port = host[:i], host[i+1:]
53 try: port = string.atoi(port)
Guido van Rossum928fced1995-09-30 16:50:46 +000054 except string.atoi_error:
55 raise socket.error, "nonnumeric port"
Guido van Rossum23acc951994-02-21 16:36:04 +000056 if not port: port = HTTP_PORT
57 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
58 if self.debuglevel > 0: print 'connect:', (host, port)
59 self.sock.connect(host, port)
60
61 def send(self, str):
62 if self.debuglevel > 0: print 'send:', `str`
63 self.sock.send(str)
64
65 def putrequest(self, request, selector):
Guido van Rossum4cdcef71995-06-22 18:48:48 +000066 if not selector: selector = '/'
Guido van Rossum23acc951994-02-21 16:36:04 +000067 str = '%s %s %s\r\n' % (request, selector, HTTP_VERSION)
68 self.send(str)
69
70 def putheader(self, header, *args):
71 str = '%s: %s\r\n' % (header, string.joinfields(args,'\r\n\t'))
72 self.send(str)
73
74 def endheaders(self):
75 self.send('\r\n')
76
Guido van Rossum23acc951994-02-21 16:36:04 +000077 def getreply(self):
Jack Jansen2bb57b81996-02-14 16:06:24 +000078 self.file = self.sock.makefile('rb')
Guido van Rossum23acc951994-02-21 16:36:04 +000079 line = self.file.readline()
80 if self.debuglevel > 0: print 'reply:', `line`
Guido van Rossum2567dd61997-08-11 21:52:17 +000081 try:
82 [ver, code, msg] = string.split(line, None, 2)
83 except ValueError:
84 self.headers = None
85 return -1, line, self.headers
86 if ver[:5] != 'HTTP/':
87 self.headers = None
88 return -1, line, self.headers
89 errcode = string.atoi(code)
90 errmsg = string.strip(msg)
Guido van Rossum65ab98c1995-08-07 20:13:02 +000091 self.headers = mimetools.Message(self.file, 0)
Guido van Rossum23acc951994-02-21 16:36:04 +000092 return errcode, errmsg, self.headers
93
94 def getfile(self):
95 return self.file
96
Guido van Rossum65ab98c1995-08-07 20:13:02 +000097 def close(self):
98 if self.file:
99 self.file.close()
100 self.file = None
Guido van Rossum2567dd61997-08-11 21:52:17 +0000101 if self.sock:
102 self.sock.close()
103 self.sock = None
Guido van Rossum65ab98c1995-08-07 20:13:02 +0000104
Guido van Rossum23acc951994-02-21 16:36:04 +0000105
106def test():
107 import sys
108 import getopt
109 opts, args = getopt.getopt(sys.argv[1:], 'd')
110 dl = 0
111 for o, a in opts:
112 if o == '-d': dl = dl + 1
Guido van Rossuma0dfc7a1995-09-07 19:28:19 +0000113 host = 'www.python.org'
114 selector = '/'
Guido van Rossum23acc951994-02-21 16:36:04 +0000115 if args[0:]: host = args[0]
116 if args[1:]: selector = args[1]
117 h = HTTP()
118 h.set_debuglevel(dl)
119 h.connect(host)
120 h.putrequest('GET', selector)
Guido van Rossuma0dfc7a1995-09-07 19:28:19 +0000121 h.endheaders()
Guido van Rossum23acc951994-02-21 16:36:04 +0000122 errcode, errmsg, headers = h.getreply()
123 print 'errcode =', errcode
Guido van Rossum23acc951994-02-21 16:36:04 +0000124 print 'errmsg =', errmsg
Guido van Rossuma0dfc7a1995-09-07 19:28:19 +0000125 print
Guido van Rossum23acc951994-02-21 16:36:04 +0000126 if headers:
127 for header in headers.headers: print string.strip(header)
Guido van Rossuma0dfc7a1995-09-07 19:28:19 +0000128 print
Guido van Rossum23acc951994-02-21 16:36:04 +0000129 print h.getfile().read()
130
Guido van Rossuma0dfc7a1995-09-07 19:28:19 +0000131
Guido van Rossum23acc951994-02-21 16:36:04 +0000132if __name__ == '__main__':
133 test()