You are not logged in Log in Join
You are here: Home » Members » adytumsolutions » PyCon2004 » ChrisHacksDonovansCode » wikipage_view

Log in
Name

Password

 
 
Zope2 Sprint » TwistedZope »

ChrisHacksDonovansCode

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)