Home:ALL Converter>twisted get body of POST request

twisted get body of POST request

Ask Time:2012-07-19T03:15:21         Author:Spencer Rathbun

Json Formatter

Ok,

This should be simple, since people do it all the time. I want to get the body of a POST request sent a twisted Agent. This is created with a twisted FileBodyProducer. On the server side, I get a request object for my render_POST method.

How do I retrieve the body?

server:

from twisted.web import server, resource
from twisted.internet import reactor


class Simple(resource.Resource):
    isLeaf = True
    def render_GET(self, request):
        return "{0}".format(request.args.keys())
    def render_POST(self, request):
        return "{0}".format(request.data)
        with open(request.args['filename'][0], 'rb') as fd:
            fd.write(request.write())

site = server.Site(Simple())
reactor.listenTCP(8080, site)
reactor.run()

client:

from StringIO import StringIO

from twisted.internet import reactor
from twisted.web.client import Agent
from twisted.web.http_headers import Headers

from twisted.web.client import FileBodyProducer
from twisted.internet.defer import Deferred
from twisted.internet.protocol import Protocol
from pprint import pformat

class BeginningPrinter(Protocol):
    def __init__(self, finished):
        self.finished = finished
        self.remaining = 1024 * 10

    def dataReceived(self, bytes):
        if self.remaining:
            display = bytes[:self.remaining]
            print 'Some data received:'
            print display
            self.remaining -= len(display)

    def connectionLost(self, reason):
        print 'Finished receiving body:', reason.getErrorMessage()
        self.finished.callback(None)

agent = Agent(reactor)
body = FileBodyProducer(StringIO("hello, world"))
d = agent.request(
    'POST',
    'http://127.0.0.1:8080/',
    Headers({'User-Agent': ['Twisted Web Client Example'],
             'Content-Type': ['text/x-greeting']}),
    body)

def cbRequest(response):
    print 'Response version:', response.version
    print 'Response code:', response.code
    print 'Response phrase:', response.phrase
    print 'Response headers:'
    print pformat(list(response.headers.getAllRawHeaders()))
    finished = Deferred()
    response.deliverBody(BeginningPrinter(finished))
    return finished
d.addCallback(cbRequest)

def cbShutdown(ignored):
    reactor.stop()
d.addBoth(cbShutdown)

reactor.run()

The only docs I can find for setting up the consumer side leave something to be desired. Primarily, how can a consumer use the write(data) method to receive results?

Which bit am I missing to plug these two components together?

Author:Spencer Rathbun,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/11548682/twisted-get-body-of-post-request
Spencer Rathbun :

All right, so it's as simple as calling request.content.read(). This, as far as I can tell, is undocumented in the API. \n\nHere's the updated code for the client:\n\nfrom twisted.internet import reactor\nfrom twisted.web.client import Agent\nfrom twisted.web.http_headers import Headers\n\nfrom twisted.web.client import FileBodyProducer\nfrom twisted.internet.defer import Deferred\nfrom twisted.internet.protocol import Protocol\nfrom pprint import pformat\n\nclass BeginningPrinter(Protocol):\n def __init__(self, finished):\n self.finished = finished\n self.remaining = 1024 * 10\n\n def dataReceived(self, bytes):\n if self.remaining:\n display = bytes[:self.remaining]\n print 'Some data received:'\n print display\n self.remaining -= len(display)\n\n def connectionLost(self, reason):\n print 'Finished receiving body:', reason.getErrorMessage()\n self.finished.callback(None)\n\nclass SaveContents(Protocol):\n def __init__(self, finished, filesize, filename):\n self.finished = finished\n self.remaining = filesize\n self.outfile = open(filename, 'wb')\n\n def dataReceived(self, bytes):\n if self.remaining:\n display = bytes[:self.remaining]\n self.outfile.write(display)\n self.remaining -= len(display)\n else:\n self.outfile.close()\n\n def connectionLost(self, reason):\n print 'Finished receiving body:', reason.getErrorMessage()\n self.outfile.close()\n self.finished.callback(None)\n\nagent = Agent(reactor)\nf = open('70935-new_barcode.pdf', 'rb')\nbody = FileBodyProducer(f)\nd = agent.request(\n 'POST',\n 'http://127.0.0.1:8080?filename=test.pdf',\n Headers({'User-Agent': ['Twisted Web Client Example'],\n 'Content-Type': ['multipart/form-data; boundary=1024'.format()]}),\n body)\n\ndef cbRequest(response):\n print 'Response version:', response.version\n print 'Response code:', response.code\n print 'Response phrase:', response.phrase\n print 'Response headers:'\n print 'Response length:', response.length\n print pformat(list(response.headers.getAllRawHeaders()))\n finished = Deferred()\n response.deliverBody(SaveContents(finished, response.length, 'test2.pdf'))\n return finished\nd.addCallback(cbRequest)\n\ndef cbShutdown(ignored):\n reactor.stop()\nd.addBoth(cbShutdown)\n\nreactor.run()\n\n\nAnd here's the server:\n\nfrom twisted.web import server, resource\nfrom twisted.internet import reactor\nimport os\n\n# multi part encoding example: http://marianoiglesias.com.ar/python/file-uploading-with-multi-part-encoding-using-twisted/\nclass Simple(resource.Resource):\n isLeaf = True\n def render_GET(self, request):\n return \"{0}\".format(request.args.keys())\n def render_POST(self, request):\n with open(request.args['filename'][0], 'wb') as fd:\n fd.write(request.content.read())\n request.setHeader('Content-Length', os.stat(request.args['filename'][0]).st_size)\n with open(request.args['filename'][0], 'rb') as fd:\n request.write(fd.read())\n request.finish()\n return server.NOT_DONE_YET\n\nsite = server.Site(Simple())\nreactor.listenTCP(8080, site)\nreactor.run()\n\n\nI can now write the file contents I receive, and read back the results. ",
2012-07-18T20:19:45
Yavor Atov :

If the content type is application/x-www-form-urlencoded or multipart/form-data,\nthe body will be parsed and put in the request.args dict.\n\nIf the body is too big, it is written in temp file, otherwise in StringIO.\n\nAfter the body is read, the method finish() is called. You can subclass Request and\npares the body in this method or do sth else.",
2012-07-31T10:04:45
yy