问题描述
我用 Python Flask-RESTful 制作了 API Server.
I made API Server with Python Flask-RESTful.
我的系统使用令牌认证来验证权限.
My system use token authentication for verify permission.
所以,我添加了用于验证令牌的中间件.
So, I added middleware for verify token.
比如这样的代码,
[中间件.py]
class Test(object): def __init__(self, app): self.app = app def __call__(self, environ, start_response): print("gogo") return self.app(environ, start_response)
[app.py]
from flask import Flask from flask_restful import Api from api.board import Article from api.auth import Login, Register, RefreshToken from middleware import Test app = Flask(__name__) api = Api(app) api.add_resource(Login, '/login') api.add_resource(Register, '/register') api.add_resource(RefreshToken, '/refresh') # middleware here app.wsgi_app = Test(app.wsgi_app) api.add_resource(Article, '/article') if __name__ == '__main__': app.run(debug=True)
我在 /article 之前插入 app.wsgi_app = Test(app.wsgi_app).
所以我希望只有访问 /article 会打印 gogo",但是每条路线都会打印 gogo".
So I expect that only access to /article will print "gogo", however every route print "gogo".
也许每条路由都经过中间件.
Maybe every route pass through with middleware.
如何为特定路由应用中间件?(在这段代码中,只有/article)
How can I apply middleware for specific route? (In this code, only /article)
推荐答案
有几种方法可以在特定端点之前添加自定义处理.
There are a few ways how to add custom processing before specific endpoint.
1)使用python装饰器:
1) Using python decorator:
from functools import wraps def home_decorator(): def _home_decorator(f): @wraps(f) def __home_decorator(*args, **kwargs): # just do here everything what you need print('before home') result = f(*args, **kwargs) print('home result: %s' % result) print('after home') return result return __home_decorator return _home_decorator @app.route('/home') @home_decorator() def home(): return 'Hello'
2) 使用 before_request
@app.before_request def hook(): # request - flask.request print('endpoint: %s, url: %s, path: %s' % ( request.endpoint, request.url, request.path)) # just do here everything what you need...
3) 使用中间件.只需在请求路径上添加条件即可.
3) Using middleware. Just add condition on request path.
class Middleware: def __init__(self, app): self.app = app def __call__(self, environ, start_response): # not Flask request - from werkzeug.wrappers import Request request = Request(environ) print('path: %s, url: %s' % (request.path, request.url)) # just do here everything what you need return self.app(environ, start_response) @app.route('/home') def home(): return 'Hello' app.wsgi_app = Middleware(app.wsgi_app)
4)您也可以使用before_request_funcs在特定蓝图之前设置函数列表.
4) Also you can use before_request_funcs to set list of functions before specific blueprint.
api = Blueprint('my_blueprint', __name__) def before_my_blueprint(): print(111) @api.route('/test') def test(): return 'hi' app.before_request_funcs = { # blueprint name: [list_of_functions] 'my_blueprint': [before_my_blueprint] } app.register_blueprint(api)
希望这会有所帮助.