I've whipped up a mod_snake adapter for Webware. It works pretty
well for me, but I'm looking for people to try it out.
If you are not currently using mod_snake, you can get it at:
modsnake.sourceforge.net
Thanks,
-- Jon
--- Snip here: snakeHandler.py --
"""
WebWare adapter for mod_snake.
- Gifted to the WebWare project by Jon Travis (jtravis@...)
Usage:
Add the following lines to your httpd.conf file:
-- Snip here --
SnakeModuleDir /path/to/WebKit
SnakeModule snakeHandler.WebWare
WebwareAddress /path/to/WebKit/address.text
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 string
import time
from marshal import dumps, loads
from socket import *
try:
from cStringIO import StringIO
except:
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
class WebWare:
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)
def create_svr_config(self, server):
return { PER_SVR_SERVER : server,
PER_SVR_PORT : None,
PER_SVR_ADDRESS : None,
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) = string.split(open(file).read(), ':')
per_svr[PER_SVR_PORT] = int(port)
per_svr[PER_SVR_ADDRESS] = host
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 "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()
dict = { 'format' : 'CGI',
'time' : time.time(),
'environ' : env,
'input' : strdata.getvalue() }
s = socket(AF_INET, SOCK_STREAM)
s.connect((per_svr[PER_SVR_ADDRESS], per_svr[PER_SVR_PORT]))
s.send(dumps(dict))
s.shutdown(1)
response = StringIO()
while 1:
data = s.recv(per_svr[PER_SVR_CHUNKSIZE])
if not data:
break
response.write(data)
# WebWare nicely returns a dictionary with content and headers
# nicely bundled. Yay!
response = loads(response.getvalue())
for key, value in response['headers']:
request.headers_out[key] = str(value)
request.content_type = request.headers_out['content-type']
if request.headers_out.has_key('status'):
request.status = int(request.headers_out['status'])
request.send_http_header()
content = response['contents']
nwrote = 0
while nwrote != len(content):
just_wrote = request.rwrite(content[nwrote:])
if just_wrote < 0:
break
nwrote = nwrote + just_wrote
return mod_snake.OK
|