【发布时间】:2013-09-16 16:08:27
【问题描述】:
我们已经实现了一个扭曲的 web api。
为了处理身份验证,我们使用了一个装饰器,我们用它来包装一些路由。
@requires_auth(roles=[Roles.Admin])
def get_secret_stuff(request):
return 42
requires_auth 包装器实现如下。
def requires_auth(roles):
def wrap(f):
def wrapped_f(request, *args, **kwargs):
# If the user is authenticated then...
return f(request, *args, **kwargs)
return wrapped_f
return wrap
问题是如果这个装饰器有多个路由,那么调用 它们中的任何一个都会导致调用要装饰的最新路由。
这显然不是我想要的,与我对装饰器应该如何工作的理解背道而驰。 我在代码中添加了一些打印语句来尝试弄清楚:
def requires_auth(roles):
def wrap(f):
print(f) # This shows that the decorator is being called correctly once per each
# route that is decorated
def wrapped_f(request, *args, **kwargs):
# If the user is authenticated then...
return f(request, *args, **kwargs)
return wrapped_f
return wrap
如果它很重要,我将使用 twisted 的 inlineCallbacks 来处理其中一些路由,以及使用 twisted web 的 @app.route(url, methods) 装饰器来处理所有这些路由。
感谢您的阅读:)
编辑: 我删除了构造函数的默认参数,因为有人告诉我这是一个坏主意:)
编辑:这是一个说明问题的最小示例:
from klein import Klein
import json
app = Klein()
def requires_auth(roles):
def wrap(f):
print('inside the first clojure with f=%s' % str(f))
def wrapped_f(request, *args, **kwargs):
print('inside the second closure with f=%s' % str(f))
return f(request, *args, **kwargs)
return wrapped_f
return wrap
@app.route('/thing_a')
@requires_auth(roles=['user'])
def get_a(request):
return json.dumps({'thing A': 'hello'})
@app.route('/thing_b')
@requires_auth(roles=['admin'])
def get_b(request):
return json.dumps({'thing B': 'goodbye'})
app.run('0.0.0.0', 8080)
去路由'/thing_a'会产生来自route_b的json
【问题讨论】:
-
不应该
wrap返回wrapped_f吗? -
是的,对不起,我错误地漏掉了,更新了。
-
你有
@requires_auth还def require_auth...注意s -
再一次,这是一个错字:p
-
能否在
wrapped_f的开头和结尾打印f以确保还是一样?