On 07/09/2013 09:04 AM, Rob Meijer wrote:
Hi everyone,

I'm working on what is just my second project using Twisted-Web, so I'm
still a relative newbee on the subject.

I'm working on a project that uses Twisted Web as a simple authorization
proxy. All requests to my proxy contain an authorization-token and are
either handled by the proxy, or are relayed to an other server. For all
GET stuff and small POST stuff this is not a problem. When I want to
process large POST requests however, I run into my limits of understanding
how Twisted Web actually works.

1) I figured out that next to the 'process' in my request handler, I need
to also overload handleContentChunk, parse the form body-parts in the
first chunk myself and open a proxy connection (self.agent.request) if the
authorization token checks out.

2) When it comes to appending the data received in handleContentChunk, and
if needed throttling the client if the server couldn't keep up,  I can't
figure out how to connect handleContentChunk and my self.agent.request
instance.

You probably want to read up on the producer/consumer stuff in Twisted. In particular if you're using t.w.client.Agent, bodies in requests are supplied by an IBodyProducer.

http://twistedmatrix.com/documents/current/web/howto/client.html

Essentially, you need an IBodyProducer that maps to the incoming transport via request, which I guess would look something like this:

class RequestProducer(object):
    implements(IBodyProducer)

    def __init__(self, request):
        self.req = request

    def startProducing(self, consumer):
        self.d = defer.Deferred()
        self.consumer = consumer
        return d

    def pauseProducing(self):
        self.req.transport.pauseProducing()

    def stopProducing(self):
        # FIXME: what to do here...
        self.req.transport.loseConnection()

    def finish():
        self.d.callback(None)

...and you'll have code like this on the request object:

    def gotLength(self, length):
        self.bodyprod = RequestProducer(self)
        if length:
            self.bodyprod.length = length
        else:
            self.bodyprod.length = twisted.web.iweb.UNKNOWN_LENGTH
        self.out_req = self.agent.request(
            'GET', url, headers, bodyprod
        )

    def handleContentChunk(self, data):
        ...
        if data_to_be_forwarded:
            self.bodyprod.consumer.write(data)
        if some_done_condition:
            self.bodyprod.finish()

3) When the token does not check out, or the connection to the server
fails, it remains a mystery to me how I should throw an error in such a
way that it allows me to send a proper error message to the client, while

This is sort of a problem with HTTP. The client will probably keep sending the data.

The best you can do is write an HTTP error to the transport then throw the connection away, or blackhole all future content chunks.

_______________________________________________
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Reply via email to