如何在GAE中覆盖HTTP请求动词

时间:2008-10-31 22:37:00

标签: python google-app-engine rest metaclass

在Google App Engine Webapp框架应用程序的上下文中:

我想在案例a中更改请求的请求动词 提供参数_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)

问题是,出于某种原因,只要重定向完成,就会出现问题 self.request.params在处理方法(put或。)时被清空 即使在初始化时填充了,也会调用delete) 调用。任何人都知道这是为什么?作为一种解决方法,我想我 可以在initialize()时克隆参数,但.copy()不起作用, 我也没有办法做到这一点。

更新:我收到了来自Arachnid的非常有帮助的回复。我最终使用的解决方案是使用元类。它位于下面。

2 个答案:

答案 0 :(得分:3)

从初始化调用处理程序不是正确的方法 - 如果你这样做,webapp也将调用原始处理程序。

相反,您有几个选择:

  • 您可以将webapp.WSGIApplication子类化并覆盖调用,以选择基于_method的方法。
  • 您可以在initialize中检查_method是否存在,如果存在,则相应地修改请求对象的'REQUEST_METHOD'环境变量。这将导致WSGIApplication类执行您选择的方法。

无论哪种方式,请查看SDK中的google / appengine / ext / webapp / init .py,以便了解其工作原理。

答案 1 :(得分:2)

Thats 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