summaryrefslogtreecommitdiffstats
path: root/Lib/httplib.py
blob: 3aeb643b641afd554c49b8a0ceeba21d2fb9f030 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# HTTP client class
#
# See the following URL for a description of the HTTP/1.0 protocol:
# http://www.w3.org/hypertext/WWW/Protocols/
# (I actually implemented it from a much earlier draft.)
#
# Example:
#
# >>> from httplib import HTTP
# >>> h = HTTP('www.python.org')
# >>> h.putrequest('GET', '/index.html')
# >>> h.putheader('Accept', 'text/html')
# >>> h.putheader('Accept', 'text/plain')
# >>> h.endheaders()
# >>> errcode, errmsg, headers = h.getreply()
# >>> if errcode == 200:
# ...     f = h.getfile()
# ...     print f.read() # Print the raw HTML
# ...
# <HEAD>
# <TITLE>Python Language Home Page</TITLE>
# [...many more lines...]
# >>>
#
# Note that an HTTP object is used for a single request -- to issue a
# second request to the same server, you create a new HTTP object.
# (This is in accordance with the protocol, which uses a new TCP
# connection for each request.)


import os
import socket
import string
import regex
import regsub
import mimetools

HTTP_VERSION = 'HTTP/1.0'
HTTP_PORT = 80

replypat = regsub.gsub('\\.', '\\\\.', HTTP_VERSION) + \
	  '[ \t]+\([0-9][0-9][0-9]\)\(.*\)'
replyprog = regex.compile(replypat)

class HTTP:

	def __init__(self, host = '', port = 0):
		self.debuglevel = 0
		self.file = None
		if host: self.connect(host, port)

	def set_debuglevel(self, debuglevel):
		self.debuglevel = debuglevel

	def connect(self, host, port = 0):
		if not port:
			i = string.find(host, ':')
			if i >= 0:
				host, port = host[:i], host[i+1:]
				try: port = string.atoi(port)
				except string.atoi_error:
				    raise socket.error, "nonnumeric port"
		if not port: port = HTTP_PORT
		self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		if self.debuglevel > 0: print 'connect:', (host, port)
		self.sock.connect(host, port)

	def send(self, str):
		if self.debuglevel > 0: print 'send:', `str`
		self.sock.send(str)

	def putrequest(self, request, selector):
		if not selector: selector = '/'
		str = '%s %s %s\r\n' % (request, selector, HTTP_VERSION)
		self.send(str)

	def putheader(self, header, *args):
		str = '%s: %s\r\n' % (header, string.joinfields(args,'\r\n\t'))
		self.send(str)

	def endheaders(self):
		self.send('\r\n')

	def getreply(self):
		self.file = self.sock.makefile('r')
		self.sock = None
		line = self.file.readline()
		if self.debuglevel > 0: print 'reply:', `line`
		if replyprog.match(line) < 0:
			self.headers = None
			return -1, line, self.headers
		errcode, errmsg = replyprog.group(1, 2)
		errcode = string.atoi(errcode)
		errmsg = string.strip(errmsg)
		self.headers = mimetools.Message(self.file, 0)
		return errcode, errmsg, self.headers

	def getfile(self):
		return self.file

	def close(self):
		if self.file:
			self.file.close()
		self.file = None


def test():
	import sys
	import getopt
	opts, args = getopt.getopt(sys.argv[1:], 'd')
	dl = 0
	for o, a in opts:
		if o == '-d': dl = dl + 1
	host = 'www.python.org'
	selector = '/'
	if args[0:]: host = args[0]
	if args[1:]: selector = args[1]
	h = HTTP()
	h.set_debuglevel(dl)
	h.connect(host)
	h.putrequest('GET', selector)
	h.endheaders()
	errcode, errmsg, headers = h.getreply()
	print 'errcode =', errcode
	print 'errmsg  =', errmsg
	print
	if headers:
		for header in headers.headers: print string.strip(header)
	print
	print h.getfile().read()


if __name__ == '__main__':
	test()