Question

I am using this middleware to make my app restful, but it looks like my form parameters are not coming through:

from google.appengine.ext import webapp

class RestHTTPMiddleware(object):
  def __init__(self, app):
    self.app = app

  def __call__(self, environ, start_response):
    method = webapp.Request(environ).get('_method')
    request = Request(environ)
    environ['wsgi.input'] = StringIO.StringIO(request.body)

    if method:
      environ['REQUEST_METHOD'] = method.upper()

    return self.app(environ, start_response)

when I submit a form and the debug it using:

def put(self):
    logging.debug(self.request.get('description'))

the logger is empty. The put(self) method is being called, I have tested it using the logger and my debug message is shown.

2nd revision:

from google.appengine.ext import webapp
from webob import Request
import logging
import StringIO

class RestHTTPMiddleware(object):
  def __init__(self, app):
    self.app = app

  def __call__(self, environ, start_response):
    request = Request(environ)
    environ['wsgi.input'] = StringIO.StringIO(request.body)

    method = webapp.Request(environ).get('_method')

    if method:
      environ['REQUEST_METHOD'] = method.upper()

    return self.app(environ, start_response)

Latest changes:

from google.appengine.ext import webapp
from webob import Request
import logging
import StringIO

class RestHTTPMiddleware(object):
  def __init__(self, app):
    self.app = app

  def __call__(self, environ, start_response):
    request = Request(environ)
    body = StringIO.StringIO(request.body)

    method = webapp.Request(environ).get('_method', None)

    if method:
      environ['REQUEST_METHOD'] = method.upper()
      environ['wsgi.input'] = body

    return self.app(environ, start_response)
Was it helpful?

Solution

Instantiating webapp.Request and calling .get on it causes it to read the request body and parse form parameters in it. When your actual webapp starts later, it instantiates another request object, and once again tries to read the request body - but it's already been read, so nothing is returned.

You could modify your middleware to store a copy of the request body and put it back in the WSGI environment. There are other options:

  • If the _method arg will always be a query string parameter instead of a posted form parameter, you can use webapp.Request(environ).GET.get('method'), which won't read the request body.
  • You could override WSGIApplication.call to change how it does dispatch.
  • You could subclass WSGIApplication and supply a custom REQUEST_CLASS, being a function that builds a real request object, then modifies the environment that was passed in to suit you (hack!).
  • You could define a custom webapp RequestHandler base class that implements initialize(), reaching in to the request object's WSGI dict and changing the method (hack!).
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top