#! /usr/bin/python import SocketServer import BaseHTTPServer import sys, traceback, socket from urlparse import urlparse, urlunparse import cgi, urllib import cc import quixote from quixote import enable_ptl, Publisher try: import thread mixin = SocketServer.ThreadingMixIn except ImportError: if not hasattr(os, 'fork'): print "ERROR: your platform does not support threading OR forking." sys.exit(1) mixin = SocketServer.ForkingMixIn class Server (mixin, BaseHTTPServer.HTTPServer): def __init__ (self, publisher, addr): self.publisher = publisher BaseHTTPServer.HTTPServer.__init__ (self, addr, QuixoteRequestHandler) def server_bind(self): # set SO_REUSEADDR (if available on this platform) if hasattr(socket, 'SOL_SOCKET') and hasattr(socket, 'SO_REUSEADDR'): self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) BaseHTTPServer.HTTPServer.server_bind(self) class format_status: def __init__ (self, wfile): self.wfile = wfile self.raw = 0 def write (self, what): if not self.raw: parts = what.split (' ', 1) if parts[0] == 'Status:': what = 'HTTP/1.0 %s' % parts[1] self.raw = 1 self.wfile.write (what) class QuixoteRequestHandler (BaseHTTPServer.BaseHTTPRequestHandler): def version_string (self): return 'QuixotePublisher 0/0 Quixote/%s' % quixote.__version__ def do_all (self): try: self.wrap_and_execute () except: self.send_response (500) self.send_header ('Content-Type', 'text/plain') self.end_headers () traceback.print_exc (file = self.wfile) do_GET = do_POST = do_HEAD = do_all def wrap_and_execute (self): rest = self.path i = rest.rfind ('?') if i >= 0: rest, query = rest[:i], rest[i+1:] else: query = '' env = {} env['GATEWAY_INTERFACE'] = 'CGI/1.1' for n, v in self.headers.items (): env['HTTP_%s' % n.upper ().replace ('-', '_')] = v env['REQUEST_METHOD'] = self.command env['PATH_INFO'] = urllib.unquote(rest) if query: env['QUERY_STRING'] = query host = self.address_string() if self.headers.typeheader is None: env['CONTENT_TYPE'] = self.headers.type else: env['CONTENT_TYPE'] = self.headers.typeheader length = self.headers.getheader('content-length') if length: env['CONTENT_LENGTH'] = length co = filter(None, self.headers.getheaders('cookie')) if co: env['HTTP_COOKIE'] = ', '.join(co) env['SCRIPT_NAME'] = '' env['SERVER_NAME'] = self.server.server_name env['SERVER_PORT'] = str(self.server.server_port) env['SERVER_PROTOCOL'] = self.protocol_version env['SERVER_SOFTWARE'] = self.version_string () env['REMOTE_ADDR'], env['REMOTE_PORT'] = map (lambda x, s = str : s (x), self.client_address) self.server.publisher.publish (self.rfile, format_status (self.wfile), sys.stderr, env) # Install the import hook that enables PTL modules. enable_ptl () # Create a Publisher instance app = Publisher ('quixote.demo') # (Optional step) Read a configuration file app.read_config ('demo.conf') # Open the configured log files app.setup_logs() httpd = Server (app, ('localhost', 8182)) try: httpd.serve_forever () except KeyboardInterrupt: print 'Quitting...' except: print 'ERROR' traceback.print_exc ()