/usr/share/pyshared/quixote/server/twisted_server.py is in python-quixote 2.7~b2-1+b2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | #!/usr/bin/env python
"""An HTTP server for Twisted that publishes a Quixote application.
"""
import urllib
from twisted.protocols import http
from twisted.web import server
from twisted.python import threadable
from twisted.internet import reactor
class QuixoteFactory(http.HTTPFactory):
def __init__(self, publisher):
self.publisher = publisher
http.HTTPFactory.__init__(self, None)
def buildProtocol(self, addr):
protocol = http.HTTPFactory.buildProtocol(self, addr)
protocol.requestFactory = QuixoteRequest
return protocol
class QuixoteRequest(server.Request):
def process(self):
environ = self.create_environment()
# this seek is important, it doesn't work without it (it doesn't
# matter for GETs, but POSTs will not work properly without it.)
self.content.seek(0, 0)
qxresponse = self.channel.factory.publisher.process(self.content,
environ)
self.setResponseCode(qxresponse.status_code)
for name, value in qxresponse.generate_headers():
if name != 'Set-Cookie':
self.setHeader(name, value)
# Cookies get special treatment since it seems Twisted cannot handle
# multiple Set-Cookie headers.
for name, attrs in qxresponse.cookies.items():
attrs = attrs.copy()
value = attrs.pop('value')
self.addCookie(name, value, **attrs)
QuixoteProducer(qxresponse, self)
def create_environment(self):
"""
Borrowed heavily from twisted.web.twcgi
"""
# Twisted doesn't decode the path for us, so let's do it here.
if '%' in self.path:
self.path = urllib.unquote(self.path)
serverName = self.getRequestHostname().split(':')[0]
env = {"SERVER_SOFTWARE": server.version,
"SERVER_NAME": serverName,
"GATEWAY_INTERFACE": "CGI/1.1",
"SERVER_PROTOCOL": self.clientproto,
"SERVER_PORT": str(self.getHost()[2]),
"REQUEST_METHOD": self.method,
"SCRIPT_NAME": '',
"SCRIPT_FILENAME": '',
"REQUEST_URI": self.uri,
"HTTPS": (self.isSecure() and 'on') or 'off',
'SERVER_PROTOCOL': 'HTTP/1.1',
}
for env_var, header in [('ACCEPT_ENCODING', 'Accept-encoding'),
('CONTENT_TYPE', 'Content-type'),
('HTTP_COOKIE', 'Cookie'),
('HTTP_REFERER', 'Referer'),
('HTTP_USER_AGENT', 'User-agent')]:
value = self.getHeader(header)
if value is not None:
env[env_var] = value
client = self.getClient()
if client is not None:
env['REMOTE_HOST'] = client
ip = self.getClientIP()
if ip is not None:
env['REMOTE_ADDR'] = ip
_, _, remote_port = self.transport.getPeer()
env['REMOTE_PORT'] = remote_port
env["PATH_INFO"] = self.path
qindex = self.uri.find('?')
if qindex != -1:
env['QUERY_STRING'] = self.uri[qindex+1:]
else:
env['QUERY_STRING'] = ''
# Propogate HTTP headers
for title, header in self.getAllHeaders().items():
envname = title.replace('-', '_').upper()
if title not in ('content-type', 'content-length'):
envname = "HTTP_" + envname
env[envname] = header
return env
class QuixoteProducer:
"""
Produce the Quixote response for twisted.
"""
def __init__(self, qxresponse, request):
self.request = request
self.size = qxresponse.get_content_length()
self.stream = qxresponse.generate_body_chunks()
request.registerProducer(self, 0)
def resumeProducing(self):
if self.request:
try:
chunk = self.stream.next()
except StopIteration:
self.request.unregisterProducer()
self.request.finish()
self.request = None
else:
self.request.write(chunk)
def pauseProducing(self):
pass
def stopProducing(self):
self.request = None
synchronized = ['resumeProducing', 'stopProducing']
threadable.synchronize(QuixoteProducer)
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)
reactor.run()
if __name__ == '__main__':
from quixote.server.util import main
main(run)
|