Letting Browsers use all of the RESTful Methods in Google App Engine
So there was much talk and whathave you about Google's new App Engine, and after viewing the tutorials and reading the documentation, I thought it was pretty rad too. Because I was using rack for some previous stuff, WSGI felt right at home (probably because rack was modeled after WSGI). There was one thing that bothered me however. When writing a class using their webapp framework there isn't any magic param name, like
_method, that I could use to mock requests methods like
PUT since the browser doesn't support those HTTP methods.
Well my friends, fear not. If you enjoy the sweet freedom of RESTful urls, I'm here to help. Since this is all built on top of WSGI, we can create a some new Middleware to sit before the application to resolve this little issue.
from google.appengine.ext import webapp class MockHTTPMethodMiddleware(object): def __init__(self, app): self.app = app def __call__(self, environ, start_response): method = webapp.Request(environ).get('_method') if method: environ['REQUEST_METHOD'] = method.upper() return self.app(environ, start_response)
The code is pretty simple. So when this middleware is called, it processes the
environ into a
Request object. From there, I just inspect the params for a key called
_method. If that param exists, then it overwrites the
REQUEST_METHOD and bam...we have mocked the HTTP method of our choosing.
Putting that code to good use
Let's pretend that this is our class is something inane like this:
from google.appengine.ext import webapp class MethodTest(webapp.RequestHandler): def get(self): self.response.headers["Content-Type"] = 'text/text' self.response.out.write("Get") def put(self): self.response.headers["Content-Type"] = 'text/text' self.response.out.write("Put")
So now when you are writing your
main method that creates the WSGI application, you would write it something like:
import wsgiref.handlers def main(): app = webapp.WSGIApplication( [('/', MethodTest)], debug=True) wsgiref.handlers.CGIHandler().run(MockHTTPMethodMiddleware(app)) if __name__ == "__main__": main()
Notice that in the run method arguments,
app as a parameter, thus
MockHTTPMethodMiddleware will run before it runs
While there wasn't support out of the box for mocking HTTP methods for browsers, with a little help from a WSGI Middleware class, it's not too hard to add that functionality in, nor is it hard to add anything else you would want to use.