3 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.)
9 >>> from httplib import HTTP
10 >>> h = HTTP('www.python.org')
11 >>> h.putrequest('GET', '/index.html')
12 >>> h.putheader('Accept', 'text/html')
13 >>> h.putheader('Accept', 'text/plain')
15 >>> errcode, errmsg, headers = h.getreply()
16 >>> if errcode == 200:
18 ... print f.read() # Print the raw HTML
21 <TITLE>Python Language Home Page</TITLE>
22 [...many more lines...]
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.)
37 from cStringIO
import StringIO
39 from StringIO
import StringIO
41 HTTP_VERSION
= 'HTTP/1.0'
46 def __init__(self
, sock
, ssl
):
51 def makefile(self
, mode
): # hopefully, never have to write
55 msgbuf
= msgbuf
+ self
.__ssl
.read()
56 except socket
.sslerror
, msg
:
58 return StringIO(msgbuf
)
60 def send(self
, stuff
, flags
= 0):
61 return self
.__ssl
.write(stuff
)
63 def recv(self
, len = 1024, flags
= 0):
64 return self
.__ssl
.read(len)
66 def __getattr__(self
, attr
):
67 return getattr(self
.__sock
, attr
)
70 """This class manages a connection to an HTTP server."""
72 def __init__(self
, host
= '', port
= 0, **x509
):
73 """Initialize a new instance.
75 If specified, `host' is the name of the remote host to which
76 to connect. If specified, `port' specifies the port to which
77 to connect. By default, httplib.HTTP_PORT is used.
80 self
.key_file
= x509
.get('key_file')
81 self
.cert_file
= x509
.get('cert_file')
84 if host
: self
.connect(host
, port
)
86 def set_debuglevel(self
, debuglevel
):
87 """Set the debug output level.
89 A non-false value results in debug messages for connection and
90 for all messages sent to and received from the server.
93 self
.debuglevel
= debuglevel
95 def connect(self
, host
, port
= 0):
96 """Connect to a host on a given port.
98 Note: This method is automatically invoked by __init__,
99 if a host is specified during instantiation.
103 i
= string
.find(host
, ':')
105 host
, port
= host
[:i
], host
[i
+1:]
106 try: port
= string
.atoi(port
)
107 except string
.atoi_error
:
108 raise socket
.error
, "nonnumeric port"
109 if not port
: port
= HTTP_PORT
110 self
.sock
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
111 if self
.debuglevel
> 0: print 'connect:', (host
, port
)
112 self
.sock
.connect(host
, port
)
115 """Send `str' to the server."""
116 if self
.debuglevel
> 0: print 'send:', `
str`
119 def putrequest(self
, request
, selector
):
120 """Send a request to the server.
122 `request' specifies an HTTP request method, e.g. 'GET'.
123 `selector' specifies the object being requested, e.g.
127 if not selector
: selector
= '/'
128 str = '%s %s %s\r\n' % (request
, selector
, HTTP_VERSION
)
131 def putheader(self
, header
, *args
):
132 """Send a request header line to the server.
134 For example: h.putheader('Accept', 'text/html')
137 str = '%s: %s\r\n' % (header
, string
.joinfields(args
,'\r\n\t'))
140 def endheaders(self
):
141 """Indicate that the last header line has been sent to the server."""
145 """Get a reply from the server.
147 Returns a tuple consisting of:
148 - server response code (e.g. '200' if all goes well)
149 - server response string corresponding to response code
150 - any RFC822 headers in the response from the server
153 self
.file = self
.sock
.makefile('rb')
154 line
= self
.file.readline()
155 if self
.debuglevel
> 0: print 'reply:', `line`
157 [ver
, code
, msg
] = string
.split(line
, None, 2)
160 [ver
, code
] = string
.split(line
, None, 1)
164 return -1, line
, self
.headers
165 if ver
[:5] != 'HTTP/':
167 return -1, line
, self
.headers
168 errcode
= string
.atoi(code
)
169 errmsg
= string
.strip(msg
)
170 self
.headers
= mimetools
.Message(self
.file, 0)
171 return errcode
, errmsg
, self
.headers
174 """Get a file object from which to receive data from the HTTP server.
176 NOTE: This method must not be invoked until getreplies
183 """Close the connection to the HTTP server."""
191 if hasattr(socket
, "ssl"):
193 """This class allows communication via SSL."""
195 def connect(self
, host
, port
= 0):
196 """Connect to a host on a given port.
198 Note: This method is automatically invoked by __init__,
199 if a host is specified during instantiation.
203 i
= string
.find(host
, ':')
205 host
, port
= host
[:i
], host
[i
+1:]
206 try: port
= string
.atoi(port
)
207 except string
.atoi_error
:
208 raise socket
.error
, "nonnumeric port"
209 if not port
: port
= HTTPS_PORT
210 sock
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
211 if self
.debuglevel
> 0: print 'connect:', (host
, port
)
212 sock
.connect(host
, port
)
213 ssl
= socket
.ssl(sock
, self
.key_file
, self
.cert_file
)
214 self
.sock
= FakeSocket(sock
, ssl
)
220 The test consists of retrieving and displaying the Python
221 home page, along with the error code and error string returned
222 by the www.python.org server.
227 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'd')
230 if o
== '-d': dl
= dl
+ 1
231 print "testing HTTP..."
232 host
= 'www.python.org'
234 if args
[0:]: host
= args
[0]
235 if args
[1:]: selector
= args
[1]
239 h
.putrequest('GET', selector
)
241 errcode
, errmsg
, headers
= h
.getreply()
242 print 'errcode =', errcode
243 print 'errmsg =', errmsg
246 for header
in headers
.headers
: print string
.strip(header
)
248 print h
.getfile().read()
249 if hasattr(socket
, "ssl"):
251 print "testing HTTPS..."
252 host
= 'synergy.as.cmu.edu'
254 if args
[0:]: host
= args
[0]
255 if args
[1:]: selector
= args
[1]
259 h
.putrequest('GET', selector
)
261 errcode
, errmsg
, headers
= h
.getreply()
262 print 'errcode =', errcode
263 print 'errmsg =', errmsg
266 for header
in headers
.headers
: print string
.strip(header
)
268 print h
.getfile().read()
271 if __name__
== '__main__':