1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
#!/usr/bin/python
"""quixote.server.medusa_http
An HTTP handler for Medusa that publishes a Quixote application.
"""
__revision__ = "$Id: medusa_http.py 25276 2004-10-06 15:46:53Z nascheme $"
# A simple HTTP server, using Medusa, that publishes a Quixote application.
import sys
import asyncore, rfc822, socket, urllib
from StringIO import StringIO
from medusa import http_server, xmlrpc_handler
from quixote.http_response import Stream
from quixote.publish import Publisher
class StreamProducer:
def __init__(self, stream):
self.iterator = iter(stream)
def more(self):
try:
return self.iterator.next()
except StopIteration:
return ''
class QuixoteHandler:
def __init__(self, publisher, server_name, server):
"""QuixoteHandler(publisher:Publisher, server_name:string,
server:medusa.http_server.http_server)
Publish the specified Quixote publisher. 'server_name' will
be passed as the SERVER_NAME environment variable.
"""
self.publisher = publisher
self.server_name = server_name
self.server = server
def match(self, request):
# Always match, since this is the only handler there is.
return 1
def handle_request(self, request):
msg = rfc822.Message(StringIO('\n'.join(request.header)))
length = int(msg.get('Content-Length', '0'))
if length:
request.collector = xmlrpc_handler.collector(self, request)
else:
self.continue_request('', request)
def continue_request(self, data, request):
msg = rfc822.Message(StringIO('\n'.join(request.header)))
remote_addr, remote_port = request.channel.addr
if '#' in request.uri:
# MSIE is buggy and sometimes includes fragments in URLs
[request.uri, fragment] = request.uri.split('#', 1)
if '?' in request.uri:
[path, query_string] = request.uri.split('?', 1)
else:
path = request.uri
query_string = ''
path = urllib.unquote(path)
server_port = str(self.server.port)
http_host = msg.get("Host")
if http_host:
if ":" in http_host:
server_name, server_port = http_host.split(":", 1)
else:
server_name = http_host
else:
server_name = (self.server.ip or
socket.gethostbyaddr(socket.gethostname())[0])
environ = {'REQUEST_METHOD': request.command,
'ACCEPT_ENCODING': msg.get('Accept-encoding', ''),
'CONTENT_TYPE': msg.get('Content-type', ''),
'CONTENT_LENGTH': len(data),
"GATEWAY_INTERFACE": "CGI/1.1",
'PATH_INFO': path,
'QUERY_STRING': query_string,
'REMOTE_ADDR': remote_addr,
'REMOTE_PORT': str(remote_port),
'REQUEST_URI': request.uri,
'SCRIPT_NAME': '',
"SCRIPT_FILENAME": '',
'SERVER_NAME': server_name,
'SERVER_PORT': server_port,
'SERVER_PROTOCOL': 'HTTP/1.1',
'SERVER_SOFTWARE': self.server_name,
}
for title, header in msg.items():
envname = 'HTTP_' + title.replace('-', '_').upper()
environ[envname] = header
stdin = StringIO(data)
qreq = self.publisher.create_request(stdin, environ)
output = self.publisher.process_request(qreq, environ)
qresponse = qreq.response
if output:
qresponse.set_body(output)
# Copy headers from Quixote's HTTP response
for name, value in qresponse.generate_headers():
# XXX Medusa's HTTP request is buggy, and only allows unique
# headers.
request[name] = value
request.response(qresponse.status_code)
# XXX should we set a default Last-Modified time?
if qresponse.body is not None:
if isinstance(qresponse.body, Stream):
request.push(StreamProducer(qresponse.body))
else:
request.push(qresponse.body)
request.done()
def main():
from quixote import enable_ptl
enable_ptl()
if len(sys.argv) == 2:
port = int(sys.argv[1])
else:
port = 8080
print 'Now serving the Quixote demo on port %d' % port
server = http_server.http_server('', port)
publisher = Publisher('quixote.demo')
# When initializing the Publisher in your own driver script,
# you'll want to parse a configuration file.
##publisher.read_config("/full/path/to/demo.conf")
publisher.setup_logs()
dh = QuixoteHandler(publisher, 'Quixote/demo', server)
server.install_handler(dh)
asyncore.loop()
if __name__ == '__main__':
main()
|