如何在GAE中重写HTTP请求动词

1 投票
2 回答
1127 浏览
提问于 2025-04-11 09:32

在Google App Engine的Web应用框架中:

我想在请求中更改请求的类型,比如当请求中有一个参数叫做_method时。如果一个POST请求进来,并且这个参数是_method=PUT,我需要把这个请求改成调用处理器的put方法。这是为了适应prototype.js对PUT和DELETE这些请求类型的处理(这是为了兼容IE浏览器)。这是我第一次尝试的代码:

class MyRequestHandler(webapp.RequestHandler):
   def initialize(self, request, response):
       m = request.get('_method')
       if m:
           request.method = m.upper()
       webapp.RequestHandler.initialize(self, request, response)

问题是,不知道为什么每次重定向后,当调用处理方法(put或delete)时,self.request.params都会变空,尽管在初始化时这些参数是有值的。有没有人知道这是为什么?作为一个解决办法,我想在initialize()时复制这些参数,但.copy()方法没有成功,我也没找到其他方法来做到这一点。

更新:我收到了Arachnid非常有帮助的回复。最后我找到的解决方案使用了元类。具体内容在下面。

2 个回答

2

这是Arachnid对你回复的内容。指引我去框架的源代码真是太有帮助了。上次我查看时,源代码并不存在(只有.pyc文件),也许随着SDK的新版本有所变化。对于我的情况,我认为重写WSGIApplication是正确的做法。不过,我选择使用元类,因为这样不需要我把框架的很多代码复制到我的代码里再进行修改。这是我的解决方案:

class RequestHandlerMetaclass(type):
    def __init__(cls, name, bases, dct):
        super(RequestHandlerMetaclass, cls).__init__(name, bases, dct)
        org_post = getattr(cls, 'post')
        def post(self, *params, **kws):
            verb = self.request.get('_method')
            if verb:
                verb = verb.upper()
                if verb ==  'DELETE':
                    self.delete(*params, **kws)
                elif verb == 'PUT':
                    self.put(*params, **kws)
            else:
                org_post(self, *params, **kws)
        setattr(cls, 'post', post)

class MyRequestHandler(webapp.RequestHandler):
    __metaclass__ = RequestHandlerMetaclass
3

从初始化中调用处理器其实不是个好方法——如果你这么做,网页应用会同时调用原来的处理器。

相反,你有几个选择:

  • 你可以创建一个新的类,继承自 webapp.WSGIApplication,并重写 call 方法,根据 _method 的值来选择要使用的方法。
  • 你可以在初始化时检查 _method 是否存在,如果存在,就相应地修改请求对象的 'REQUEST_METHOD' 环境变量。这样,WSGIApplication 类就会执行你选择的方法。

无论你选择哪种方式,都可以看看 SDK 中的 google/appengine/ext/webapp/init.py 文件,了解它是如何工作的。

撰写回答