History for ChrisHacksDonovansCode
??changed:
-
import os
import sys
import string
#import base64
#from cStringIO import StringIO
from twisted.protocols import http
from twisted.python import log
from twisted.web import static, server, twcgi, resource
from twisted.application import service, internet
here = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(here, 'lib', 'python'))
from ZPublisher.Publish import publish_module
from ZPublisher import HTTPResponse
#log.startLogging(file('twisted.log', 'w'))
def setupzope():
import Zope
Zope.configure(os.path.join(here, 'etc', 'zope.conf'))
Zope.startup()
__version__ = 1
port = 6969
class ZopeResource(resource.Resource):
"""
A very minimal twisted Resource
"""
def __init__(self, data):
self.response = data
class ZopeRequest(server.Request):
"""
Adapt twisted Requests to zope
"""
def render(self, resource):
"""
Override twisted's server.Request.render method
to do what Zope needs with the response
"""
response = resource.response
self.transport.write('HTTP/1.1 %s %s\r\n' % (
response.status, http.responses[response.status]))
self.transport.write(str(response))
self.transport.loseConnection()
def get_cgi_env(self):
"""
Setup the special CGI environment variables Zope
needs in order to function properly
"""
script_name = "/"+string.join(self.prepath, '/')
python_path = string.join(sys.path, os.pathsep)
serverName = string.split(self.getRequestHostname(), ':')[0]
auth = self.getHeader('Authorization')
cookie = self.getHeader('cookie')
referer = self.getHeader('referer')
query = ''
try:
query = self.uri.split('?', 1)[1]
except:
query = ''
env = {
"SERVER_SOFTWARE": 'ZTwisted' , # 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_name, # XXX
"REQUEST_URI": self.uri,
"PATH_INFO": self.path,
"HTTP_AUTHORIZATION": auth,
"HTTP_COOKIE": cookie,
"HTTP_REFERER": referer,
"QUERY_STRING": query,
}
ct = self.getHeader('content-type')
if ct:
env['CONTENT_TYPE'] = ct
cl = self.getHeader('content-length')
if cl:
env['CONTENT_LENGTH'] = cl
return env
class Dummy:
"""
This is used later to redirect stdout
"""
def write(self, data):
"""
like /dev/null
"""
pass
class ZopeSite(server.Site):
"""
Twisted representation of a Zope app
"""
requestFactory = ZopeRequest
def getResourceFor(self, request):
"""
get a twisted ZopeResource (HTTP Response data)
by using ZPublisher to traverse Zope objects
"""
stdout = Dummy()
env = request.get_cgi_env()
request.content.seek(0,0)
response = HTTPResponse.HTTPResponse()
publish_module('Zope', stdin=request.content,
stdout=stdout, environ=env, response=response)
return ZopeResource(response)
"""
Note that in the Twisted paradigm, the previous code would be
in a .py file and the following code would be in a separate .tac
file which would import the code above and be run with twistd;
see example code from the Nevow project and Twisted documentation
for details.
One of the major missing thing is obviously the equivalent of
ZRendezvous to do thread pool management. Right now, it's single-
threaded.
"""
if __name__ == '__main__':
print 'ERROR: Run this via twistd -noy %s' % __file__
sys.exit(1)
setupzope()
application = service.Application("twisted-zope")
internet.TCPServer(port, ZopeSite(None)).setServiceParent(application)