2006/06/30
I was recently hunting for some docs on how to handle POST requests in Cherrypy 2.2 yourself, in stead of having the CP machinery decoding the variables for you.
“Why do you want to do this?” you may ask.
Well, in my case, I wanted to do some simple RPC calls to my server, but I wanted to do something even simpler than XMLRPC or JSONRPC. Specifically I didn’t want all my calls to be routed through a single URL, and have the methodnames be dispatched based on some paramter in the message payload. Rather I want to be able to do a POST on a URL where the body of my request contains a JSON serialized data packet, which is the paramters of my call. This is in spirit similar to those other RPC-over-HTTP schemes, but simpler and more in the HTTP spirit IMNHO.
Calling it, you want to do something like:
import httplib, simplejson h = httplib.HTTPConnection('localhost:8080') z = {'a':123, 'b':456} h.request('POST', '/rpc', simplejson.dumps(z)) r = h.getresponse() r.read() # But I have wrapped it up in a utility class, so you can also do: p = ssrpc.Proxy('localhost:8080') p.rpc(a=123, b=456)
I found some examples on the CherryPy Wiki at http://www.cherrypy.org/wiki/FileUpload which started me on the way, and looking at tutorial_09 in the CherryPy distribution also helped. Some light reading of the source, and I came up with the following code for doing the server-side in CherryPy 2.2:
import cherrypy import simplejson class StreamFilter(cherrypy.filters.basefilter.BaseFilter): def before_request_body(self): if cherrypy.request.path == '/rpc': # if you don't check that it is a post method the server might lock up # we also check to make sure something was submitted if not 'Content-Length' in cherrypy.request.headerMap or \ (cherrypy.request.method != 'POST'): raise cherrypy.HTTPRedirect('/') else: # Tell CherryPy not to parse the POST data itself for this URL cherrypy.request.processRequestBody = False # class Root: _cpFilterList = [StreamFilter()] def index(self): return """Testing POST handling in body.
""" index.exposed = True def rpc(self): dataLength = int(cherrypy.request.headers.get('Content-Length') or 0) data = cherrypy.request.rfile.read(dataLength) o = simplejson.loads(data) return "You asked: %s" % o rpc.exposed = True cherrypy.root = Root() cherrypy.server.start()
Hope these snippets help someone else looking to do the same thing.