SVN: r25579 - in trunk/quixote: . demo server
Neil Schemenauer <nascheme-fVcApmY9cLvQ3/1i3zOLAti2O/[email protected]> Thu, 11 Nov 2004 15:56:49 -0500
| Newsgroups | gmane.comp.web.quixote.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: nascheme
Date: 2004-11-11 15:56:32 -0500 (Thu, 11 Nov 2004)
New Revision: 25579
Added:
trunk/quixote/server/simple_server.py
trunk/quixote/server/util.py
Removed:
trunk/quixote/demo/demonstrate.py
Modified:
trunk/quixote/demo/altdemo.py
trunk/quixote/http_response.py
trunk/quixote/server/__init__.py
trunk/quixote/server/medusa_server.py
trunk/quixote/server/scgi_server.py
trunk/quixote/server/twisted_server.py
trunk/quixote/util.py
Log:
Move the option parser out of the demonstrate.py script and make it
available to the stand alone HTTP servers. Move the simple HTTP server
from the demonstrate.py script to server/simple_server.py.
Modified: trunk/quixote/demo/altdemo.py
===================================================================
--- trunk/quixote/demo/altdemo.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/demo/altdemo.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -2,9 +2,16 @@
$Id$
An alternative Quixote demo. This version is contained in a single module
-and does not use PTL.
+and does not use PTL. The easiest way to run this demo is to use the
+simple HTTP server included with Quixote. For example:
+
+ $ server/simple_server.py --factory quixote.demo.altdemo.create_publisher
+
+The server listens on localhost:8080 by default. Debug and error output
+will be sent to the terminal.
"""
from quixote import get_response
+from quixote.publish import Publisher
from quixote.directory import Directory
from quixote.errors import PublishError
from quixote.html import href
@@ -85,3 +92,5 @@
sub = SubDirectory()
+def create_publisher():
+ return Publisher(RootDirectory(), display_exceptions='plain')
Deleted: trunk/quixote/demo/demonstrate.py
===================================================================
--- trunk/quixote/demo/demonstrate.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/demo/demonstrate.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -1,113 +0,0 @@
-#!/usr/bin/env python
-"""
-$URL$
-$Id$
-
-Run a simple HTTPServer on a local port, processing all requests
-using a Quixote Directory instance. Command line options allow
-the specification of Directory and/or Publisher classes.
-"""
-import sys
-from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
-from quixote import enable_ptl
-from quixote.http_request import HTTPRequest
-from quixote.publish import get_publisher
-
-class HTTPRequestHandler(BaseHTTPRequestHandler):
-
- def get_cgi_env(self, method):
- env = dict(
- SERVER_SOFTWARE="demonstrate.py/1.0",
- SERVER_NAME=self.server.server_name,
- GATEWAY_INTERFACE='CGI/1.1',
- SERVER_PROTOCOL=self.protocol_version,
- SERVER_PORT=str(self.server.server_port),
- REQUEST_METHOD=method,
- REMOTE_ADDR=self.client_address[0],
- SCRIPT_NAME='')
- if '?' in self.path:
- env['PATH_INFO'], env['QUERY_STRING'] = self.path.split('?')
- else:
- env['PATH_INFO'] = self.path
- if self.headers.typeheader is None:
- env['CONTENT_TYPE'] = self.headers.type
- else:
- env['CONTENT_TYPE'] = self.headers.typeheader
- env['CONTENT_LENGTH'] = self.headers.getheader('content-length') or "0"
- accept = []
- for line in self.headers.getallmatchingheaders('accept'):
- if line[:1] in "\t\n\r ":
- accept.append(line.strip())
- else:
- accept = accept + line[7:].split(',')
- env['HTTP_ACCEPT'] = ','.join(accept)
- ua = self.headers.getheader('user-agent')
- if ua:
- env['HTTP_USER_AGENT'] = ua
- co = filter(None, self.headers.getheaders('cookie'))
- if co:
- env['HTTP_COOKIE'] = ', '.join(co)
- return env
-
- def process(self, env):
- request = HTTPRequest(self.rfile, env)
- response = get_publisher().process_request(request)
- try:
- self.send_response(response.get_status_code(),
- 'Script output follows')
- response.write(self.wfile)
- except IOError, err:
- print "IOError while sending response ignored: %s" % err
-
- def do_POST(self):
- return self.process(self.get_cgi_env('POST'))
-
- def do_GET(self):
- return self.process(self.get_cgi_env('GET'))
-
-def demo_directory(port=8000,
- root_directory='quixote.demo.DemoUI',
- publisher='quixote.publish.Publisher'):
- enable_ptl()
- def import_class(name):
- i = name.rfind('.')
- module_name = name[:i]
- class_name = name[i+1:]
- __import__(module_name)
- return getattr(sys.modules[module_name], class_name)
- root_directory_instance = import_class(root_directory)()
- if get_publisher() is None:
- publisher_class = import_class(publisher)
- publisher_class(root_directory_instance, display_exceptions='plain')
- HTTPRequestHandler.protocol_version = 'HTTP/1.0'
- httpd = HTTPServer(('', port), HTTPRequestHandler)
- sa = httpd.socket.getsockname()
- print "Serving HTTP on", sa[0], "port", sa[1], "..."
- httpd.serve_forever()
-
-if __name__ == '__main__':
- from optparse import OptionParser
- parser = OptionParser()
- parser.set_description(
- "Runs a simple HTTP server that processes all requests "
- "through a Directory.\n "
- "This is for demonstration purposes only.\n")
- default_port = 8000
- parser.add_option(
- '--port', dest="port", default=default_port,
- type="int",
- help="Port for the server to listen on. (default=%s)" % default_port)
- default_root_directory = 'quixote.demo.root.RootDirectory'
- parser.add_option(
- '--directory', dest="root_directory",
- default=default_root_directory,
- help="The root Directory class. (default=%s)" % default_root_directory)
- default_publisher = 'quixote.publish.Publisher'
- parser.add_option(
- '--publisher', dest="publisher",
- default=default_publisher,
- help="The Publisher class. (default=%s)" % default_publisher)
- (options, args) = parser.parse_args()
- demo_directory(port=options.port,
- root_directory=options.root_directory,
- publisher = options.publisher)
Modified: trunk/quixote/http_response.py
===================================================================
--- trunk/quixote/http_response.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/http_response.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -327,6 +327,9 @@
def get_status_code(self):
return self.status_code
+
+ def get_reason_phrase(self):
+ return self.reason_phrase
def get_content_length(self):
if self.body is None:
Modified: trunk/quixote/server/__init__.py
===================================================================
--- trunk/quixote/server/__init__.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/server/__init__.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -1,5 +1,5 @@
"""$URL$
$Id$
-This package is for Quixote/HTTP server glue.
+This package is for Quixote to server glue.
"""
Modified: trunk/quixote/server/medusa_server.py
===================================================================
--- trunk/quixote/server/medusa_server.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/server/medusa_server.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -8,6 +8,7 @@
import asyncore, rfc822, socket, urllib
from StringIO import StringIO
from medusa import http_server, xmlrpc_handler
+import quixote
from quixote.http_request import HTTPRequest
@@ -78,7 +79,7 @@
'SERVER_NAME': server_name,
'SERVER_PORT': server_port,
'SERVER_PROTOCOL': 'HTTP/1.1',
- 'SERVER_SOFTWARE': 'Quixote/2',
+ 'SERVER_SOFTWARE': 'Quixote/%s' % quixote.__version__,
}
for title, header in msg.items():
envname = 'HTTP_' + title.replace('-', '_').upper()
@@ -100,6 +101,9 @@
def run(create_publisher, host='', port=80):
+ """Runs a Medusa HTTP server that publishes a Quixote
+ application.
+ """
server = http_server.http_server(host, port)
publisher = create_publisher()
handler = QuixoteHandler(publisher, server)
@@ -108,5 +112,5 @@
if __name__ == '__main__':
- from quixote.demo import create_publisher
- run(create_publisher, port=8080)
+ from quixote.server.util import main
+ main(run)
Modified: trunk/quixote/server/scgi_server.py
===================================================================
--- trunk/quixote/server/scgi_server.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/server/scgi_server.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -48,6 +48,37 @@
s.serve()
+def main():
+ from optparse import OptionParser
+ from quixote.util import import_object
+ parser = OptionParser()
+ parser.set_description(run.__doc__)
+ default_host = 'localhost'
+ parser.add_option(
+ '--host', dest="host", default=default_host, type="string",
+ help="Host interface to listen on. (default=%s)" % default_host)
+ default_port = 3000
+ parser.add_option(
+ '--port', dest="port", default=default_port, type="int",
+ help="Port to listen on. (default=%s)" % default_port)
+ default_maxchild = 5
+ parser.add_option(
+ '--max-children', dest="maxchild", default=default_maxchild,
+ type="string",
+ help="Maximum number of children to spawn. (default=%s)" %
+ default_maxchild)
+ parser.add_option(
+ '--script-name', dest="script_name", default=None, type="string",
+ help="Value of SCRIPT_NAME (only needed if using mod_scgi)")
+ default_factory = 'quixote.demo.create_publisher'
+ parser.add_option(
+ '--factory', dest="factory",
+ default=default_factory,
+ help="Path to factory function to create the site Publisher. "
+ "(default=%s)" % default_factory)
+ (options, args) = parser.parse_args()
+ run(import_object(options.factory), host=options.host, port=options.port,
+ script_name=options.script_name, max_children=options.maxchild)
+
if __name__ == '__main__':
- from quixote.demo import create_publisher
- run(create_publisher)
+ main()
Added: trunk/quixote/server/simple_server.py
===================================================================
--- trunk/quixote/server/simple_server.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/server/simple_server.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+"""$URL$
+$Id$
+
+A simple, single threaded, synchronous HTTP server.
+"""
+from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+import quixote
+from quixote import get_publisher
+from quixote.http_request import HTTPRequest
+
+class HTTPRequestHandler(BaseHTTPRequestHandler):
+
+ def get_cgi_env(self, method):
+ env = dict(
+ SERVER_SOFTWARE="Quixote/%s" % quixote.__version__,
+ SERVER_NAME=self.server.server_name,
+ GATEWAY_INTERFACE='CGI/1.1',
+ SERVER_PROTOCOL=self.protocol_version,
+ SERVER_PORT=str(self.server.server_port),
+ REQUEST_METHOD=method,
+ REMOTE_ADDR=self.client_address[0],
+ SCRIPT_NAME='')
+ if '?' in self.path:
+ env['PATH_INFO'], env['QUERY_STRING'] = self.path.split('?')
+ else:
+ env['PATH_INFO'] = self.path
+ if self.headers.typeheader is None:
+ env['CONTENT_TYPE'] = self.headers.type
+ else:
+ env['CONTENT_TYPE'] = self.headers.typeheader
+ env['CONTENT_LENGTH'] = self.headers.getheader('content-length') or "0"
+ accept = []
+ for line in self.headers.getallmatchingheaders('accept'):
+ if line[:1] in "\t\n\r ":
+ accept.append(line.strip())
+ else:
+ accept = accept + line[7:].split(',')
+ env['HTTP_ACCEPT'] = ','.join(accept)
+ ua = self.headers.getheader('user-agent')
+ if ua:
+ env['HTTP_USER_AGENT'] = ua
+ co = filter(None, self.headers.getheaders('cookie'))
+ if co:
+ env['HTTP_COOKIE'] = ', '.join(co)
+ return env
+
+ def process(self, env):
+ request = HTTPRequest(self.rfile, env)
+ response = get_publisher().process_request(request)
+ try:
+ self.send_response(response.get_status_code(),
+ response.get_reason_phrase())
+ response.write(self.wfile)
+ except IOError, err:
+ print "IOError while sending response ignored: %s" % err
+
+ def do_POST(self):
+ return self.process(self.get_cgi_env('POST'))
+
+ def do_GET(self):
+ return self.process(self.get_cgi_env('GET'))
+
+
+def run(create_publisher, host='', port=80):
+ """Runs a simple, single threaded, synchronous HTTP server that
+ publishes a Quixote application.
+ """
+ httpd = HTTPServer((host, port), HTTPRequestHandler)
+ publisher = create_publisher()
+ httpd.serve_forever()
+
+
+if __name__ == '__main__':
+ from quixote.server.util import main
+ main(run)
Property changes on: trunk/quixote/server/simple_server.py
___________________________________________________________________
Name: svn:keywords
+ HeadURL Id
Modified: trunk/quixote/server/twisted_server.py
===================================================================
--- trunk/quixote/server/twisted_server.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/server/twisted_server.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -127,6 +127,8 @@
def run(create_publisher, host='', port=80):
+ """Runs a Twisted HTTP server server that publishes a Quixote
+ application."""
publisher = create_publisher()
factory = QuixoteFactory(publisher)
reactor.listenTCP(port, factory, interface=host)
@@ -134,5 +136,5 @@
if __name__ == '__main__':
- from quixote.demo import create_publisher
- run(create_publisher, port=8080)
+ from quixote.server.util import main
+ main(run)
Added: trunk/quixote/server/util.py
===================================================================
--- trunk/quixote/server/util.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/server/util.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -0,0 +1,28 @@
+"""$URL$
+$Id$
+
+Miscellaneous utility functions shared by servers.
+"""
+
+from optparse import OptionParser
+from quixote.util import import_object
+
+def main(run):
+ parser = OptionParser()
+ parser.set_description(run.__doc__)
+ default_host = 'localhost'
+ parser.add_option(
+ '--host', dest="host", default=default_host, type="string",
+ help="Host interface to listen on. (default=%s)" % default_host)
+ default_port = 8080
+ parser.add_option(
+ '--port', dest="port", default=default_port, type="int",
+ help="Port to listen on. (default=%s)" % default_port)
+ default_factory = 'quixote.demo.create_publisher'
+ parser.add_option(
+ '--factory', dest="factory",
+ default=default_factory,
+ help="Path to factory function to create the site Publisher. "
+ "(default=%s)" % default_factory)
+ (options, args) = parser.parse_args()
+ run(import_object(options.factory), host=options.host, port=options.port)
Property changes on: trunk/quixote/server/util.py
___________________________________________________________________
Name: svn:keywords
+ HeadURL Id
Modified: trunk/quixote/util.py
===================================================================
--- trunk/quixote/util.py 2004-11-11 20:39:03 UTC (rev 25578)
+++ trunk/quixote/util.py 2004-11-11 20:56:32 UTC (rev 25579)
@@ -68,6 +68,13 @@
randbytes = _PRNG().randbytes
+def import_object(name):
+ i = name.rfind('.')
+ module_name = name[:i]
+ object_name = name[i+1:]
+ __import__(module_name)
+ return getattr(sys.modules[module_name], object_name)
+
def xmlrpc(request, func):
"""xmlrpc(request:Request, func:callable) : string