I made API Server with Python Flask-RESTful.
My system use token authentication for verify permission.
So, I added middleware for verify token.
For example, code like this,
[middleware.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)
I insert app.wsgi_app = Test(app.wsgi_app)
before /article
.
So I expect that only access to /article
will print "gogo", however every route print "gogo".
Maybe every route pass through with middleware.
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) 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) Using 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) 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) 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)