Python 应用引擎 put(self):
我正在使用这个中间件来让我的应用程序变得更符合RESTful风格,但看起来我的表单参数没有传过来:
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)
当我提交一个表单并用以下方式调试它时:
def put(self):
logging.debug(self.request.get('description'))
日志记录器是空的。put(self)这个方法被调用了,我用日志记录器测试过,调试信息是显示出来的。
第二次修订:
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)
最新的更改:
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)
1 个回答
4
当你创建一个webapp.Request对象并调用它的.get方法时,它会读取请求的内容并解析里面的表单参数。等到你的实际web应用程序启动时,它又会创建一个新的请求对象,再次尝试读取请求的内容,但这时候内容已经被读取过了,所以什么也得不到。
你可以修改你的中间件,保存一份请求内容的副本,然后再把它放回WSGI环境中。还有其他一些选择:
- 如果_method参数总是作为查询字符串参数而不是表单参数来传递,你可以使用webapp.Request(environ).GET.get('method'),这样就不会读取请求的内容。
- 你可以重写WSGIApplication.call方法,来改变它的分发方式。
- 你可以创建一个WSGIApplication的子类,并提供一个自定义的REQUEST_CLASS,这个类是一个构建真实请求对象的函数,然后修改传入的环境以适应你的需求(这算是个小技巧!)。
- 你可以定义一个自定义的webapp RequestHandler基类,里面实现initialize()方法,直接修改请求对象的WSGI字典中的方法(这也是个小技巧!)。