Hi Matt I'd certainly be interested in seeing that script, as I'd like to compare it against the one below, which was my solution to the same problem. However I dont really know enough about twisted to be sure this was the right way to do it. To be honest i cobbled this together after looking at twisted_http.py and scanning some of the twisted src files. twisted/web/twcgi may well have been a better place to start had I known it existed! Cheers Jon from twisted.protocols import http from twisted.web import proxy,server from twisted.internet import reactor, protocol HTTP_PORT = 8098 SCGI_PORT = 4000 SCGI_PROTOCOL_VERSION = "1" class SCGIProtocol(protocol.Protocol): def __init__(self,request): self.request = request self.data = "" def connectionMade(self): self.transport.write(self.request.get_scgi_netstring()) def connectionLost(self, reason): self.request.write(self.data.replace("Status:","HTTP/1.1")) self.request.finish() def dataReceived(self,data): self.data += data class SCGIReverseProxyRequest(proxy.ReverseProxyRequest): def process(self): scgi_ns=self.get_scgi_netstring() cc = protocol.ClientCreator(reactor,SCGIProtocol,self) df = cc.connectTCP("localhost", SCGI_PORT) self.startedWriting = 1 def get_scgi_netstring (self): host = self.getHeader('host') or self.getHost() serverName = host.split(':')[0] content_type = self.getHeader('content-type') typ, remote_addr, remote_port = self.transport.getPeer() t = range(22) bdy = self.content.read() t[0] = "CONTENT_LENGTH",str(len(bdy or "")) t[1]= "SCGI", SCGI_PROTOCOL_VERSION t[2]= "SERVER_SOFTWARE", server.version or "" t[3]= "SERVER_PROTOCOL", self.clientproto or "" t[4]= "SERVER_NAME", serverName or "" t[5]= "SERVER_ADMIN", "" t[6]= "SERVER_ADDR", "" t[7]= "SERVER_PORT", str(HTTP_PORT) t[8]= "REMOTE_ADDR", self.getClientIP() or "" t[9]= "REMOTE_PORT", str(remote_port) or "" t[10]= "REMOTE_USER", self.getUser() or "" t[11]= "REQUEST_METHOD", self.method or "" t[12]= "REQUEST_URI", self.uri or "" x = self.uri.split('?', 2) if len(x) == 2: t[13]= "QUERY_STRING", x[1] or "" else: t[13]= "QUERY_STRING","" t[14]= "SCRIPT_NAME", self.uri t[15]= "HTTP_USER_AGENT", self.getHeader("User-Agent") or "" t[16]= "HTTP_COOKIE", self.getHeader("Cookie") or "" t[17]= "HTTPS", "" #lookup_env(r, "HTTPS") t[18]= "CONTENT_TYPE", self.getHeader("Content-type") or "" t[19]= "DOCUMENT_ROOT", "" #ap_document_root(r) t[20]= "HTTP_ACCEPT", self.getHeader("Accept") or "" t[21]= "HTTP_REFERER", self.getHeader("Referer") or "" ### now make a netstring buffer="".join([ "%s\0%s\0" % i for i in t]) ns = "%lu:%s,%s" % (len(buffer),buffer,bdy) return ns class SCGIReverseProxy(proxy.ReverseProxy): requestFactory = SCGIReverseProxyRequest def main(): f = http.HTTPFactory() f.protocol = SCGIReverseProxy reactor.listenTCP(HTTP_PORT, f) reactor.run() if __name__ == '__main__': main()