Index: twisted/web/proxy.py =================================================================== --- twisted/web/proxy.py (revision 33657) +++ twisted/web/proxy.py (working copy) @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.web.test.test_proxy -*- -# Copyright (c) Twisted Matrix Laboratories. +# Copyright (c) 2001-2010 Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -40,6 +40,32 @@ _finished = False def __init__(self, command, rest, version, headers, data, father): + """ + Usually created when ProxyClientFactory.buildProtocol is called. + The arguments passed to this __init__ are the same as the ones passed + to ProxyClientFactory.__init__. + @type command: C{str} + @param command: HTTP Command (GET, POST, HEAD, etc) + + @type rest: C{str} + @param rest: Rest of url other than host, ex. example.com/test.html + /test.html is the rest + + @type version: C{str} + @param version: HTTP Version (HTTP/1.1, HTTP/1.0) + + @type headers: C{dict} + @param headers: The headers that were specified in the request to + (or through) the proxy server + + @type data: C{str} + @param data: Data sent to (or through) the server for example with a + POST requst + + @type father: C{ProxyRequest) + @param father: The server request first passed to the ProxyClientFactory + and then the ProxyClient when buildProtocol is called + """ self.father = father self.command = command self.rest = rest @@ -60,10 +86,28 @@ def handleStatus(self, version, code, message): + """ + Handles the status sent from the remote server back to the client. + Passes it onto the proxy server and then back to the user. + @param version: HTTP Version (HTTP/1.1. HTTP/1.0) + @param code: HTTP status code (200, 404, 403, etc) + @param message: Message sent with the status + """ self.father.setResponseCode(int(code), message) def handleHeader(self, key, value): + """ + Handles a header sent from the remote server back to the client + Passes the header back to the proxy server and then back to the user + + @type key: C{str} + @param key: An HTTP header field name. + + @type value: C{str} + @param value: An HTTP header field value. + """ + # t.web.server.Request sets default values for these headers in its # 'process' method. When these headers are received from the remote # server, they ought to override the defaults, rather than append to @@ -75,11 +119,19 @@ def handleResponsePart(self, buffer): + """ + Handles some data received by the client. + Writes the data back to the proxy server. + + @type buffer: C{str} + @param buffer: The data that was received from the remote server. + """ self.father.write(buffer) def handleResponseEnd(self): """ + Handles the end of the connection to the remote server. Finish the original request, indicating that the response has been completely written to it, and disconnect the outgoing transport. """ @@ -99,6 +151,31 @@ def __init__(self, command, rest, version, headers, data, father): + """ + Copied from equivalent arguments passed to the protocol + @type command: C{str} + @param command: HTTP Command (GET, POST, HEAD, etc) + + @type rest: C{str} + @param rest: Rest of url other than host, ex. example.com/test.html + /test.html is the rest + + @type version: C{str} + @param version: HTTP Version (HTTP/1.1, HTTP/1.0) + + @type headers: C{str} + @param headers: The headers that were specified in the request to + (or through) the proxy server + + @type data: C{str} + @param data: Data sent to (or through) the server for example with a + POST requst + + @type father: C{ProxyRequest} + @param father: The server request first passed to the ProxyClientFactory + and then the ProxyClient when buildProtocol is called + + """ self.father = father self.command = command self.rest = rest @@ -108,6 +185,10 @@ def buildProtocol(self, addr): + """ + Builds ProxyClient, passing the arugments set in __init__, and returns + the protocol + """ return self.protocol(self.command, self.rest, self.version, self.headers, self.data, self.father) @@ -136,11 +217,33 @@ ports = {'http': 80} def __init__(self, channel, queued, reactor=reactor): + """ + Implements the proxy server's request handler see + + @type channel: C{Proxy} + @param channel: Used as connection between your client and the proxy server + + @type queued: C{bool} + @param queued: Is the request queued or can we write to the transport now? + + @type reactor: L{twisted.internet.reactor} + @param reactor: Needed here to connect the Proxy client end to the remote server + """ Request.__init__(self, channel, queued) self.reactor = reactor def process(self): + """ + Called to process the request from your client + This method parses the url (to see what the proxy needs to go fetch) and + then connects to that url (just like if your program connect to example.com + except the proxy server does it not your client directly) using the class + specified in protocols. + Overide if you want to control things such as headers and method sent to + the remote server (for example if you want any GET request to change to a + HEAD request) + """ parsed = urlparse.urlparse(self.uri) protocol = parsed[0] host = parsed[1] @@ -167,7 +270,7 @@ """ This class implements a simple web proxy. - Since it inherits from L{twisted.web.http.HTTPChannel}, to use it you + Since it inherits from L{twisted.protocols.http.HTTPChannel}, to use it you should do something like this:: from twisted.web import http @@ -176,6 +279,12 @@ Make the HTTPFactory a listener on a port as per usual, and you have a fully-functioning web proxy! + + The HTTP channel that your client and the proxy server communicate over. + Subclasses HTTPChannel and just changes what request factory to use so + instead of using one that say servers files you use C{ProxyRequest) to then + connect to a remote host and serve that instead of boring files. + """ requestFactory = ProxyRequest @@ -220,7 +329,7 @@ """ Implements a simple reverse proxy. - For details of usage, see the file examples/reverse-proxy.py. + For details of usage, see the file examples/proxy.py. """ requestFactory = ReverseProxyRequest @@ -301,3 +410,4 @@ request.getAllHeaders(), request.content.read(), request) self.reactor.connectTCP(self.host, self.port, clientFactory) return NOT_DONE_YET +