blob: 2e7bb3ff38f7fd360c469e889204103a10df8372 [file] [log] [blame]
Guido van Rossume7e578f1995-08-04 04:00:20 +00001"""HTTP server base class.
2
3Note: the class in this module doesn't implement any HTTP request; see
4SimpleHTTPServer for simple implementations of GET, HEAD and POST
Martin v. Löwis587c98c2002-03-17 18:37:22 +00005(including CGI scripts). It does, however, optionally implement HTTP/1.1
6persistent connections, as of version 0.3.
Guido van Rossume7e578f1995-08-04 04:00:20 +00007
8Contents:
9
10- BaseHTTPRequestHandler: HTTP request handler base class
11- test: test function
12
13XXX To do:
14
Guido van Rossume7e578f1995-08-04 04:00:20 +000015- log requests even later (to capture byte count)
16- log user-agent header and other interesting goodies
17- send error log to separate file
Guido van Rossume7e578f1995-08-04 04:00:20 +000018"""
19
20
21# See also:
22#
23# HTTP Working Group T. Berners-Lee
24# INTERNET-DRAFT R. T. Fielding
25# <draft-ietf-http-v10-spec-00.txt> H. Frystyk Nielsen
26# Expires September 8, 1995 March 8, 1995
27#
28# URL: http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-v10-spec-00.txt
Martin v. Löwis587c98c2002-03-17 18:37:22 +000029#
30# and
31#
32# Network Working Group R. Fielding
33# Request for Comments: 2616 et al
34# Obsoletes: 2068 June 1999
Tim Peters863ac442002-04-16 01:38:40 +000035# Category: Standards Track
Martin v. Löwis587c98c2002-03-17 18:37:22 +000036#
37# URL: http://www.faqs.org/rfcs/rfc2616.html
Guido van Rossume7e578f1995-08-04 04:00:20 +000038
39# Log files
40# ---------
Tim Peters11cf6052001-01-14 21:54:20 +000041#
Guido van Rossume7e578f1995-08-04 04:00:20 +000042# Here's a quote from the NCSA httpd docs about log file format.
Tim Peters11cf6052001-01-14 21:54:20 +000043#
44# | The logfile format is as follows. Each line consists of:
45# |
46# | host rfc931 authuser [DD/Mon/YYYY:hh:mm:ss] "request" ddd bbbb
47# |
48# | host: Either the DNS name or the IP number of the remote client
Guido van Rossume7e578f1995-08-04 04:00:20 +000049# | rfc931: Any information returned by identd for this person,
Tim Peters11cf6052001-01-14 21:54:20 +000050# | - otherwise.
Guido van Rossume7e578f1995-08-04 04:00:20 +000051# | authuser: If user sent a userid for authentication, the user name,
Tim Peters11cf6052001-01-14 21:54:20 +000052# | - otherwise.
53# | DD: Day
54# | Mon: Month (calendar name)
55# | YYYY: Year
56# | hh: hour (24-hour format, the machine's timezone)
57# | mm: minutes
58# | ss: seconds
59# | request: The first line of the HTTP request as sent by the client.
60# | ddd: the status code returned by the server, - if not available.
Guido van Rossume7e578f1995-08-04 04:00:20 +000061# | bbbb: the total number of bytes sent,
Tim Peters11cf6052001-01-14 21:54:20 +000062# | *not including the HTTP/1.0 header*, - if not available
63# |
Guido van Rossume7e578f1995-08-04 04:00:20 +000064# | You can determine the name of the file accessed through request.
Tim Peters11cf6052001-01-14 21:54:20 +000065#
Guido van Rossume7e578f1995-08-04 04:00:20 +000066# (Actually, the latter is only true if you know the server configuration
67# at the time the request was made!)
68
Martin v. Löwis587c98c2002-03-17 18:37:22 +000069__version__ = "0.3"
Guido van Rossume7e578f1995-08-04 04:00:20 +000070
Skip Montanaroe99d5ea2001-01-20 19:54:20 +000071__all__ = ["HTTPServer", "BaseHTTPRequestHandler"]
Guido van Rossume7e578f1995-08-04 04:00:20 +000072
73import sys
74import time
75import socket # For gethostbyaddr()
Guido van Rossume7e578f1995-08-04 04:00:20 +000076import mimetools
77import SocketServer
Martin v. Löwis587c98c2002-03-17 18:37:22 +000078import cStringIO
Guido van Rossume7e578f1995-08-04 04:00:20 +000079
80# Default error message
81DEFAULT_ERROR_MESSAGE = """\
82<head>
83<title>Error response</title>
84</head>
85<body>
86<h1>Error response</h1>
87<p>Error code %(code)d.
88<p>Message: %(message)s.
89<p>Error code explanation: %(code)s = %(explain)s.
90</body>
91"""
92
93
94class HTTPServer(SocketServer.TCPServer):
95
Guido van Rossum18865de2000-05-09 14:54:13 +000096 allow_reuse_address = 1 # Seems to make sense in testing environment
97
Guido van Rossume7e578f1995-08-04 04:00:20 +000098 def server_bind(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000099 """Override server_bind to store the server name."""
100 SocketServer.TCPServer.server_bind(self)
101 host, port = self.socket.getsockname()
Peter Schneider-Kamp2d2785a2000-08-16 20:30:21 +0000102 self.server_name = socket.getfqdn(host)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000103 self.server_port = port
Guido van Rossume7e578f1995-08-04 04:00:20 +0000104
105
106class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
107
108 """HTTP request handler base class.
109
110 The following explanation of HTTP serves to guide you through the
111 code as well as to expose any misunderstandings I may have about
112 HTTP (so you don't need to read the code to figure out I'm wrong
113 :-).
114
115 HTTP (HyperText Transfer Protocol) is an extensible protocol on
116 top of a reliable stream transport (e.g. TCP/IP). The protocol
117 recognizes three parts to a request:
118
119 1. One line identifying the request type and path
120 2. An optional set of RFC-822-style headers
121 3. An optional data part
122
123 The headers and data are separated by a blank line.
124
125 The first line of the request has the form
126
127 <command> <path> <version>
128
129 where <command> is a (case-sensitive) keyword such as GET or POST,
130 <path> is a string containing path information for the request,
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000131 and <version> should be the string "HTTP/1.0" or "HTTP/1.1".
132 <path> is encoded using the URL encoding scheme (using %xx to signify
133 the ASCII character with hex code xx).
Guido van Rossume7e578f1995-08-04 04:00:20 +0000134
135 The protocol is vague about whether lines are separated by LF
136 characters or by CRLF pairs -- for compatibility with the widest
137 range of clients, both should be accepted. Similarly, whitespace
138 in the request line should be treated sensibly (allowing multiple
139 spaces between components and allowing trailing whitespace).
140
141 Similarly, for output, lines ought to be separated by CRLF pairs
142 but most clients grok LF characters just fine.
143
144 If the first line of the request has the form
145
146 <command> <path>
147
148 (i.e. <version> is left out) then this is assumed to be an HTTP
149 0.9 request; this form has no optional headers and data part and
150 the reply consists of just the data.
151
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000152 The reply form of the HTTP 1.x protocol again has three parts:
Guido van Rossume7e578f1995-08-04 04:00:20 +0000153
154 1. One line giving the response code
155 2. An optional set of RFC-822-style headers
156 3. The data
157
158 Again, the headers and data are separated by a blank line.
159
160 The response code line has the form
161
162 <version> <responsecode> <responsestring>
163
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000164 where <version> is the protocol version ("HTTP/1.0" or "HTTP/1.1"),
Guido van Rossume7e578f1995-08-04 04:00:20 +0000165 <responsecode> is a 3-digit response code indicating success or
166 failure of the request, and <responsestring> is an optional
167 human-readable string explaining what the response code means.
168
169 This server parses the request and the headers, and then calls a
170 function specific to the request type (<command>). Specifically,
Guido van Rossumba895d81999-09-15 15:28:25 +0000171 a request SPAM will be handled by a method do_SPAM(). If no
Guido van Rossume7e578f1995-08-04 04:00:20 +0000172 such method exists the server sends an error response to the
173 client. If it exists, it is called with no arguments:
174
175 do_SPAM()
176
177 Note that the request name is case sensitive (i.e. SPAM and spam
178 are different requests).
179
180 The various request details are stored in instance variables:
181
182 - client_address is the client IP address in the form (host,
183 port);
184
185 - command, path and version are the broken-down request line;
186
187 - headers is an instance of mimetools.Message (or a derived
188 class) containing the header information;
189
190 - rfile is a file object open for reading positioned at the
191 start of the optional input data part;
192
193 - wfile is a file object open for writing.
194
195 IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING!
196
197 The first thing to be written must be the response line. Then
198 follow 0 or more header lines, then a blank line, and then the
199 actual data (if any). The meaning of the header lines depends on
200 the command executed by the server; in most cases, when data is
201 returned, there should be at least one header line of the form
202
203 Content-type: <type>/<subtype>
204
205 where <type> and <subtype> should be registered MIME types,
206 e.g. "text/html" or "text/plain".
207
208 """
209
210 # The Python system version, truncated to its first component.
Eric S. Raymondb49f4a42001-02-09 05:07:04 +0000211 sys_version = "Python/" + sys.version.split()[0]
Guido van Rossume7e578f1995-08-04 04:00:20 +0000212
213 # The server software version. You may want to override this.
214 # The format is multiple whitespace-separated strings,
215 # where each string is of the form name[/version].
216 server_version = "BaseHTTP/" + __version__
217
Guido van Rossumd65b5391999-10-26 13:01:36 +0000218 def parse_request(self):
219 """Parse a request (internal).
Guido van Rossume7e578f1995-08-04 04:00:20 +0000220
Guido van Rossumd65b5391999-10-26 13:01:36 +0000221 The request should be stored in self.raw_request; the results
222 are in self.command, self.path, self.request_version and
223 self.headers.
224
Tim Petersbc0e9102002-04-04 22:55:58 +0000225 Return True for success, False for failure; on failure, an
Guido van Rossumd65b5391999-10-26 13:01:36 +0000226 error is sent back.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000227
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000228 """
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000229 self.request_version = version = "HTTP/0.9" # Default
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000230 self.close_connection = 1
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000231 requestline = self.raw_requestline
232 if requestline[-2:] == '\r\n':
233 requestline = requestline[:-2]
234 elif requestline[-1:] == '\n':
235 requestline = requestline[:-1]
236 self.requestline = requestline
Eric S. Raymondb49f4a42001-02-09 05:07:04 +0000237 words = requestline.split()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000238 if len(words) == 3:
239 [command, path, version] = words
240 if version[:5] != 'HTTP/':
241 self.send_error(400, "Bad request version (%s)" % `version`)
Tim Petersbc0e9102002-04-04 22:55:58 +0000242 return False
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000243 try:
244 version_number = float(version.split('/', 1)[1])
245 except ValueError:
246 self.send_error(400, "Bad request version (%s)" % `version`)
Tim Petersbc0e9102002-04-04 22:55:58 +0000247 return False
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000248 if version_number >= 1.1 and self.protocol_version >= "HTTP/1.1":
249 self.close_connection = 0
250 if version_number >= 2.0:
251 self.send_error(505,
252 "Invalid HTTP Version (%f)" % version_number)
Tim Petersbc0e9102002-04-04 22:55:58 +0000253 return False
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000254 elif len(words) == 2:
255 [command, path] = words
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000256 self.close_connection = 1
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000257 if command != 'GET':
258 self.send_error(400,
259 "Bad HTTP/0.9 request type (%s)" % `command`)
Tim Petersbc0e9102002-04-04 22:55:58 +0000260 return False
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000261 elif not words:
Tim Petersbc0e9102002-04-04 22:55:58 +0000262 return False
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000263 else:
264 self.send_error(400, "Bad request syntax (%s)" % `requestline`)
Tim Petersbc0e9102002-04-04 22:55:58 +0000265 return False
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000266 self.command, self.path, self.request_version = command, path, version
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000267
268 # Deal with pipelining
269 bytes = ""
270 while 1:
271 line = self.rfile.readline()
272 bytes = bytes + line
273 if line == '\r\n' or line == '\n' or line == '':
274 break
275
276 # Examine the headers and look for a Connection directive
277 hfile = cStringIO.StringIO(bytes)
278 self.headers = self.MessageClass(hfile)
279
280 conntype = self.headers.get('Connection', "")
281 if conntype.lower() == 'close':
282 self.close_connection = 1
283 elif (conntype.lower() == 'keep-alive' and
284 self.protocol_version >= "HTTP/1.1"):
285 self.close_connection = 0
Tim Petersbc0e9102002-04-04 22:55:58 +0000286 return True
Guido van Rossumd65b5391999-10-26 13:01:36 +0000287
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000288 def handle_one_request(self):
Guido van Rossumd65b5391999-10-26 13:01:36 +0000289 """Handle a single HTTP request.
290
291 You normally don't need to override this method; see the class
292 __doc__ string for information on how to handle specific HTTP
293 commands such as GET and POST.
294
295 """
Guido van Rossumd65b5391999-10-26 13:01:36 +0000296 self.raw_requestline = self.rfile.readline()
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000297 if not self.raw_requestline:
298 self.close_connection = 1
299 return
Guido van Rossumd65b5391999-10-26 13:01:36 +0000300 if not self.parse_request(): # An error code has been sent, just exit
301 return
302 mname = 'do_' + self.command
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000303 if not hasattr(self, mname):
Guido van Rossumd65b5391999-10-26 13:01:36 +0000304 self.send_error(501, "Unsupported method (%s)" % `self.command`)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000305 return
306 method = getattr(self, mname)
307 method()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000308
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000309 def handle(self):
310 """Handle multiple requests if necessary."""
311 self.close_connection = 1
312
313 self.handle_one_request()
314 while not self.close_connection:
315 self.handle_one_request()
316
Guido van Rossume7e578f1995-08-04 04:00:20 +0000317 def send_error(self, code, message=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000318 """Send and log an error reply.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000319
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000320 Arguments are the error code, and a detailed message.
321 The detailed message defaults to the short entry matching the
322 response code.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000323
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000324 This sends an error response (so it must be called before any
325 output has been generated), logs the error, and finally sends
326 a piece of HTML explaining the error to the user.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000327
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000328 """
Guido van Rossume7e578f1995-08-04 04:00:20 +0000329
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000330 try:
331 short, long = self.responses[code]
332 except KeyError:
333 short, long = '???', '???'
Raymond Hettingerc0418602002-05-31 23:03:33 +0000334 if message is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000335 message = short
336 explain = long
337 self.log_error("code %d, message %s", code, message)
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000338 content = (self.error_message_format %
339 {'code': code, 'message': message, 'explain': explain})
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000340 self.send_response(code, message)
Skip Montanaro31fd86c2002-03-08 02:36:18 +0000341 self.send_header("Content-Type", "text/html")
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000342 self.send_header('Connection', 'close')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000343 self.end_headers()
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000344 if self.command != 'HEAD' and code >= 200 and code not in (204, 304):
345 self.wfile.write(content)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000346
347 error_message_format = DEFAULT_ERROR_MESSAGE
348
349 def send_response(self, code, message=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000350 """Send the response header and log the response code.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000351
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000352 Also send two standard headers with the server software
353 version and the current date.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000354
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000355 """
356 self.log_request(code)
357 if message is None:
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000358 if code in self.responses:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000359 message = self.responses[code][0]
360 else:
361 message = ''
362 if self.request_version != 'HTTP/0.9':
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000363 self.wfile.write("%s %d %s\r\n" %
364 (self.protocol_version, code, message))
365 # print (self.protocol_version, code, message)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000366 self.send_header('Server', self.version_string())
367 self.send_header('Date', self.date_time_string())
Guido van Rossume7e578f1995-08-04 04:00:20 +0000368
369 def send_header(self, keyword, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000370 """Send a MIME header."""
371 if self.request_version != 'HTTP/0.9':
372 self.wfile.write("%s: %s\r\n" % (keyword, value))
Guido van Rossume7e578f1995-08-04 04:00:20 +0000373
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000374 if keyword.lower() == 'connection':
375 if value.lower() == 'close':
376 self.close_connection = 1
377 elif value.lower() == 'keep-alive':
378 self.close_connection = 0
379
Guido van Rossume7e578f1995-08-04 04:00:20 +0000380 def end_headers(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000381 """Send the blank line ending the MIME headers."""
382 if self.request_version != 'HTTP/0.9':
383 self.wfile.write("\r\n")
Guido van Rossume7e578f1995-08-04 04:00:20 +0000384
385 def log_request(self, code='-', size='-'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000386 """Log an accepted request.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000387
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000388 This is called by send_reponse().
Guido van Rossume7e578f1995-08-04 04:00:20 +0000389
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000390 """
Guido van Rossume7e578f1995-08-04 04:00:20 +0000391
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000392 self.log_message('"%s" %s %s',
393 self.requestline, str(code), str(size))
Guido van Rossume7e578f1995-08-04 04:00:20 +0000394
395 def log_error(self, *args):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000396 """Log an error.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000397
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000398 This is called when a request cannot be fulfilled. By
399 default it passes the message on to log_message().
Guido van Rossume7e578f1995-08-04 04:00:20 +0000400
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000401 Arguments are the same as for log_message().
Guido van Rossume7e578f1995-08-04 04:00:20 +0000402
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000403 XXX This should go to the separate error log.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000404
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000405 """
Guido van Rossume7e578f1995-08-04 04:00:20 +0000406
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000407 apply(self.log_message, args)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000408
409 def log_message(self, format, *args):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000410 """Log an arbitrary message.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000411
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000412 This is used by all other logging functions. Override
413 it if you have specific logging wishes.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000414
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000415 The first argument, FORMAT, is a format string for the
416 message to be logged. If the format string contains
417 any % escapes requiring parameters, they should be
418 specified as subsequent arguments (it's just like
419 printf!).
Guido van Rossume7e578f1995-08-04 04:00:20 +0000420
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000421 The client host and current date/time are prefixed to
422 every message.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000423
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000424 """
Guido van Rossume7e578f1995-08-04 04:00:20 +0000425
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000426 sys.stderr.write("%s - - [%s] %s\n" %
427 (self.address_string(),
428 self.log_date_time_string(),
429 format%args))
Guido van Rossume7e578f1995-08-04 04:00:20 +0000430
431 def version_string(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000432 """Return the server software version string."""
433 return self.server_version + ' ' + self.sys_version
Guido van Rossume7e578f1995-08-04 04:00:20 +0000434
435 def date_time_string(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000436 """Return the current date and time formatted for a message header."""
437 now = time.time()
438 year, month, day, hh, mm, ss, wd, y, z = time.gmtime(now)
439 s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
440 self.weekdayname[wd],
441 day, self.monthname[month], year,
442 hh, mm, ss)
443 return s
Guido van Rossume7e578f1995-08-04 04:00:20 +0000444
445 def log_date_time_string(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000446 """Return the current time formatted for logging."""
447 now = time.time()
448 year, month, day, hh, mm, ss, x, y, z = time.localtime(now)
449 s = "%02d/%3s/%04d %02d:%02d:%02d" % (
450 day, self.monthname[month], year, hh, mm, ss)
451 return s
Guido van Rossume7e578f1995-08-04 04:00:20 +0000452
453 weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
454
455 monthname = [None,
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000456 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
457 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
Guido van Rossume7e578f1995-08-04 04:00:20 +0000458
459 def address_string(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000460 """Return the client address formatted for logging.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000461
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000462 This version looks up the full hostname using gethostbyaddr(),
463 and tries to find a name that contains at least one dot.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000464
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000465 """
Guido van Rossume7e578f1995-08-04 04:00:20 +0000466
Peter Schneider-Kamp2d2785a2000-08-16 20:30:21 +0000467 host, port = self.client_address
468 return socket.getfqdn(host)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000469
470 # Essentially static class variables
471
472 # The version of the HTTP protocol we support.
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000473 # Set this to HTTP/1.1 to enable automatic keepalive
Guido van Rossume7e578f1995-08-04 04:00:20 +0000474 protocol_version = "HTTP/1.0"
475
476 # The Message-like class used to parse headers
477 MessageClass = mimetools.Message
478
479 # Table mapping response codes to messages; entries have the
480 # form {code: (shortmessage, longmessage)}.
481 # See http://www.w3.org/hypertext/WWW/Protocols/HTTP/HTRESP.html
482 responses = {
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000483 100: ('Continue', 'Request received, please continue'),
484 101: ('Switching Protocols',
485 'Switching to new protocol; obey Upgrade header'),
486
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000487 200: ('OK', 'Request fulfilled, document follows'),
488 201: ('Created', 'Document created, URL follows'),
489 202: ('Accepted',
490 'Request accepted, processing continues off-line'),
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000491 203: ('Non-Authoritative Information', 'Request fulfilled from cache'),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000492 204: ('No response', 'Request fulfilled, nothing follows'),
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000493 205: ('Reset Content', 'Clear input form for further input.'),
494 206: ('Partial Content', 'Partial content follows.'),
Tim Peters11cf6052001-01-14 21:54:20 +0000495
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000496 300: ('Multiple Choices',
497 'Object has several resources -- see URI list'),
498 301: ('Moved Permanently', 'Object moved permanently -- see URI list'),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000499 302: ('Found', 'Object moved temporarily -- see URI list'),
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000500 303: ('See Other', 'Object moved -- see Method and URL list'),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000501 304: ('Not modified',
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000502 'Document has not changed since given time'),
503 305: ('Use Proxy',
504 'You must use proxy specified in Location to access this '
505 'resource.'),
506 307: ('Temporary Redirect',
507 'Object moved temporarily -- see URI list'),
Tim Peters11cf6052001-01-14 21:54:20 +0000508
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000509 400: ('Bad request',
510 'Bad request syntax or unsupported method'),
511 401: ('Unauthorized',
512 'No permission -- see authorization schemes'),
513 402: ('Payment required',
514 'No payment -- see charging schemes'),
515 403: ('Forbidden',
516 'Request forbidden -- authorization will not help'),
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000517 404: ('Not Found', 'Nothing matches the given URI'),
518 405: ('Method Not Allowed',
519 'Specified method is invalid for this server.'),
520 406: ('Not Acceptable', 'URI not available in preferred format.'),
521 407: ('Proxy Authentication Required', 'You must authenticate with '
522 'this proxy before proceeding.'),
523 408: ('Request Time-out', 'Request timed out; try again later.'),
524 409: ('Conflict', 'Request conflict.'),
525 410: ('Gone',
526 'URI no longer exists and has been permanently removed.'),
527 411: ('Length Required', 'Client must specify Content-Length.'),
528 412: ('Precondition Failed', 'Precondition in headers is false.'),
529 413: ('Request Entity Too Large', 'Entity is too large.'),
530 414: ('Request-URI Too Long', 'URI is too long.'),
531 415: ('Unsupported Media Type', 'Entity body in unsupported format.'),
532 416: ('Requested Range Not Satisfiable',
533 'Cannot satisfy request range.'),
534 417: ('Expectation Failed',
535 'Expect condition could not be satisfied.'),
Tim Peters11cf6052001-01-14 21:54:20 +0000536
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000537 500: ('Internal error', 'Server got itself in trouble'),
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000538 501: ('Not Implemented',
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000539 'Server does not support this operation'),
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000540 502: ('Bad Gateway', 'Invalid responses from another server/proxy.'),
541 503: ('Service temporarily overloaded',
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000542 'The server cannot process the request due to a high load'),
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000543 504: ('Gateway timeout',
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000544 'The gateway server did not receive a timely response'),
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000545 505: ('HTTP Version not supported', 'Cannot fulfill request.'),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000546 }
Guido van Rossume7e578f1995-08-04 04:00:20 +0000547
548
549def test(HandlerClass = BaseHTTPRequestHandler,
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000550 ServerClass = HTTPServer, protocol="HTTP/1.0"):
Guido van Rossume7e578f1995-08-04 04:00:20 +0000551 """Test the HTTP request handler class.
552
553 This runs an HTTP server on port 8000 (or the first command line
554 argument).
555
556 """
557
558 if sys.argv[1:]:
Eric S. Raymond5ff63d62001-02-09 05:38:46 +0000559 port = int(sys.argv[1])
Guido van Rossume7e578f1995-08-04 04:00:20 +0000560 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000561 port = 8000
Guido van Rossume7e578f1995-08-04 04:00:20 +0000562 server_address = ('', port)
563
Martin v. Löwis587c98c2002-03-17 18:37:22 +0000564 HandlerClass.protocol_version = protocol
Guido van Rossume7e578f1995-08-04 04:00:20 +0000565 httpd = ServerClass(server_address, HandlerClass)
566
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000567 sa = httpd.socket.getsockname()
568 print "Serving HTTP on", sa[0], "port", sa[1], "..."
Guido van Rossume7e578f1995-08-04 04:00:20 +0000569 httpd.serve_forever()
570
571
572if __name__ == '__main__':
573 test()