how do I write a middleware for tornado?

2019-06-05 14:15发布

问题:

Every request to a handler in my tornado app need to check and validate a key before it processes the request. How could I create a middleware class in Tornado which would check and validate the key before if processes the request?

My middleware class function would look something like this.

class Checker(object):

    def process_request(self, request):
        try:
            key = request.META['HTTP_X_KEY']
        except KeyError:
            key = None

        if key and key == os.environ.get('KEY'):
            #Process the request
            return None
        #Redirect to Home Page
        return HttpResponsePermanentRedirect('http://google.com', status=301)

回答1:

It is possible to use decorator:

from functools import wraps
def check_key(f):
    @wraps(f)
    def wrapper(self, request):
        try:
            key = request.META['HTTP_X_KEY']
        except KeyError:
            key = None
        if key and key == os.environ.get('KEY'):
            #Process the request
            f(self, request)
            return None
        #Redirect to Home Page
        return HttpResponsePermanentRedirect('http://google.com', status=301)
    return wrapper

class Checker(object):
   @check_key
   def process_request(self, request):
      ...


回答2:

You can hook up middleware, actually. HTTPServer request handlers are just callable objects (function, methods, or objects that implement __call__). You can write your own handler that passes on requests to your Application:

my_app = tornado.web.Application(...)

def middleware(request):
    # do whatever transformation you want here
    my_app(request)

if __name__ == '__main__':
    http_server = tornado.httpserver.HTTPServer(middleware)
    # ...`

Since Tornado request handling can be asynchronous, you can't modify the response in your middleware, but you can at least work with the request.