"""WebWare adapter for mod_snake.
Gifted to the WebWare project by Jon Travis (jtravis@covalent.net).
mod_snake is a plugin for Apache which allows modules to be written
in Python, and have the same power as C modules. In addition it
accelerates Python written CGI, similar to Py_Apache and mod_python
and includes support for HTML with embedded Python.
You can download mod_snake at: http://sourceforge.net/projects/modsnake
Usage:
Add the following lines to your httpd.conf file:
-- Snip here --
SnakeModuleDir /path/to/Webware
SnakeModuleDir /path/to/Webware/WebKit
SnakeModule ModSnakeAdapter.ModSnakeAdapter
WebwareAddress /path/to/Webware/WebKit/adapter.address
AddHandler webware .psp
<Location /wpy>
SetHandler webware
</Location>
-- Snip here --
Using the above configuration will tag all .psp files for processing
by the Webware handler. All files in the /wpy location will also be
given the same handler.
To change the chunk size that the mod_snake adaptor uses for reading
and writing data, simply add the directive:
WebwareChunkSize 69
(or whatever your new chunksize is)
"""
import mod_snake
import os
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
# Keys into the server-config dictionary
PER_SVR_SERVER = 0 # server_rec
PER_SVR_PORT = 1 # Port from webware address file
PER_SVR_ADDRESS = 2 # Address from webware address file
PER_SVR_CHUNKSIZE = 3 # Size of chunks to read and write
DEFAULT_CHUNKSIZE = 32 * 1024
from WebKit.Adapters.Adapter import Adapter
class ModSnakeAdapter(Adapter):
def __init__(self, module):
hooks = {
'create_svr_config' : self.create_svr_config,
'content_handler': self.content_handler,
}
for hook in hooks.keys():
module.add_hook(hook, hooks[hook])
directives = {
'WebwareAddress' : (mod_snake.RSRC_CONF,mod_snake.TAKE1,
self.cmd_WebwareAddress),
'WebwareChunkSize': (mod_snake.RSRC_CONF,mod_snake.TAKE1,
self.cmd_WebwareChunkSize)
}
module.add_directives(directives)
Adapter.__init__(self, '')
def create_svr_config(self, server):
return {
PER_SVR_SERVER: server,
PER_SVR_PORT: '8086',
PER_SVR_ADDRESS: 'localhost',
PER_SVR_CHUNKSIZE: DEFAULT_CHUNKSIZE,
}
def cmd_WebwareChunkSize(self, per_dir, per_svr, chunksize):
chunksize = int(chunksize)
if chunksize <= 0:
return "chunksize must be > 0"
per_svr[PER_SVR_CHUNKSIZE] = int(chunksize)
def cmd_WebwareAddress(self, per_dir, per_svr, file):
host, port = open(file).read().split(':')
per_svr[PER_SVR_PORT] = int(port)
per_svr[PER_SVR_ADDRESS] = host
self._webKitDir = os.path.dirname(file)
def content_handler(self, per_dir, per_svr, request):
if request.handler != 'webware':
return mod_snake.DECLINED
res = request.setup_client_block(mod_snake.REQUEST_CHUNKED_ERROR)
if res:
raise IOError("Failed to setup client blocking method")
request.should_client_block()
strdata = StringIO()
while 1:
data, err = request.get_client_block(per_svr[PER_SVR_CHUNKSIZE])
if err <= 0:
break
strdata.write(data)
# Setup the subprocess environment, because os.environ suxx0r3z
request.add_common_vars()
request.add_cgi_vars()
env = {}
for key, val in request.subprocess_env.items():
env[key] = val
env["GATEWAY_INTERFACE"] = mod_snake.get_version()
response = self.transactWithAppServer(env, strdata.getvalue(), \
per_svr[PER_SVR_ADDRESS], per_svr[PER_SVR_PORT])
self.respond( request, response)
return mod_snake.OK
def respond(self, req, respdict):
headerend = respdict.find("\n\n")
headers = respdict[:headerend]
for header in headers.split("\n"):
header = header.split(":")
field = header[0]
req.headers_out[field] = ":".join(header[1:])
field = field.lower()
if field == 'content-type':
req.content_type = header[1]
elif field == 'status':
req.status = int(header[1].lstrip().split(' ', 1)[0])
req.send_http_header()
req.rwrite(respdict[headerend+2:])
|