Python 应用引擎 put(self):

1 投票
1 回答
1278 浏览
提问于 2025-04-15 20:30

我正在使用这个中间件来让我的应用程序变得更符合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字典中的方法(这也是个小技巧!)。

撰写回答