[albatross-users] New version of the standalone http server
Matt Goodall
matt at pollenation.net
Thu Jul 3 11:40:45 EST 2003
Hi all,
Attached is an updated version of the standalone server with the
following changes:
* Fixed to support forms containing input fields with a "list"
attribute. It only ever returned the first value in the get or
post data before.
* Added the current working directory to the path so that the
httpd.py script can live anywhere.
* changed the filename to al-httpd. An even better name might be
al-simple-server.
Cheers, Matt
--
Matt Goodall, Pollenation Internet Ltd
w: http://www.pollenation.net
e: matt at pollenation.net
-------------- next part --------------
#!/usr/bin/env python
import BaseHTTPServer
import cgi
import os
import sys
from cStringIO import StringIO
from urlparse import urlsplit
class Request:
"""BaseHTTPServer request adaptor"""
def __init__(self, req):
self._req = req
self._status = 200;
self._fields = []
self.headers_out = {}
self.data = StringIO()
if self._req.command == 'GET':
self._fields = self.parse_get_fields()
elif self._req.command == 'POST':
self._fields = self.parse_post_fields()
else:
pass
def parse_get_fields(self):
"""Extract fields from query string"""
qs = urlsplit(self._req.requestline.split()[1])[3]
if not qs:
return {}
return cgi.parse_qs(qs)
def parse_post_fields(self):
"""Extract fields from posted data"""
fields = {}
content_type = self._req.headers.get('content-type')
if content_type:
key, pdict = cgi.parse_header(content_type)
if key == 'application/x-www-form-urlencoded':
cl = int(self._req.headers['content-length'])
fields = cgi.parse_qs(self._req.rfile.read(cl), 1)
elif key == 'multipart/form-data':
fields = cgi.parse_multipart(self.content, pdict)
else:
pass
return fields
def get_header(self, name):
return self._req.headers.get(name)
def write_header(self, name, value):
self.headers_out[name] = value
def end_headers(self):
pass
def has_field(self, name):
return self._fields.has_key(name)
def field_value(self, name):
# Get the field
field = self._fields[name]
# Field is always a list. If there is only one item in it then return
# the item and let Albatross take care of input fields with the list
# attribute
if len(field) == 1:
return field[0]
else:
return field
def field_names(self):
return self._fields.keys()
def get_uri(self):
serverName = self._req.server.server_name
serverPort = self._req.server.server_port
path = self._req.path
uri = 'http://%s:%d%s' % (serverName, serverPort, path)
return uri
def get_servername(self):
servername = self._req.server.server_name
port = self._req.server.server_port
return '%s:%d' % (servername, port)
def write_content(self, data):
self.data.write(data)
def redirect(self, loc):
self.write_header('Location', loc)
self.write_header('Status', '301 Moved Permanently')
self._status = 301
self.end_headers()
def set_status(self, status):
self._status = status
def status(self):
return self._status
class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""
Handle HTTP request, routing them through to the Albatross
application
"""
def do_GET(self):
self.process_request()
def do_POST(self):
self.process_request()
def process_request(self):
self.log_request()
req = Request(self)
self.server.app.run(req)
self.send_response(req.status())
for name, value in req.headers_out.items():
self.send_header(name, value)
self.end_headers()
if req.status() == 200:
self.wfile.write(req.data.getvalue())
class HTTPServer(BaseHTTPServer.HTTPServer):
"""Simple, standalone HTTP server for Albatross applications."""
def __init__(self, app, port):
BaseHTTPServer.HTTPServer.__init__(self, ('', port), RequestHandler)
self.app = app
if __name__ == '__main__':
# Append the current working directory to the path
sys.path.append(os.getcwd())
# Parse the command line
appClass = sys.argv[1]
port = int(sys.argv[2])
# Load the application's module and create an application instance
module = __import__(appClass[:appClass.rindex('.')])
app = getattr(module,appClass[appClass.rindex('.')+1:])()
# Create the HTTP server
httpd = HTTPServer(app, port)
# Handle requests
httpd.serve_forever()
More information about the Albatross-users
mailing list