7

I have two after_request handlers. In my case, I need one to fire before the next.

@app.after_request
    def after_request_check_something(response):
        # do something
        return response

@app.after_request
    def after_request_compress(response):
        # do something
        return response

In my case, I want compress to go first, then check_something. But they are firing in reverse.

If it matters, in my actual code, these two handlers are not consecutively declared like this. They are each in different modules that are installed at different times.

How can I control the order of execution?

101010
  • 14,866
  • 30
  • 95
  • 172

2 Answers2

13

Flask's after_request hooks are indeed executed in the reversed order of their declaration. Conversely, before_request hooks are executed in the order of their declaration.

If after_request hooks are declared on a blueprint, those are executed in reversed declaration order, before global after_request hooks. If before_request hooks are declared on a blueprint, those are executed in declaration order, after global before_request hooks.

See preprocess_request and process_response source code for implementation details.

user8808265
  • 1,893
  • 1
  • 17
  • 25
2

Edit: user8808265's answer looks more correct than mine.

From the documentation, it does not appear that the execution of these after_request handlers can be ordered. The implementation has the handlers stored in a dictionary which is inherently unordered.

I suggest making a separate handler that calls both in the correct order, something like:

def after_request_check_something(response):
    # do something
    return response


def after_request_compress(response):
    # do something
    return response

@app.after_request
def after_request_combined(response):
    response1 = after_request_compress(response)
    return after_request_check_something(response1)
Andrii Rubtsov
  • 524
  • 3
  • 13
Frank T
  • 8,268
  • 8
  • 50
  • 67
  • 1
    If they're stored in a dictionary then a possible solution could be [use Python 3.6](http://stackoverflow.com/questions/39980323/dictionaries-are-ordered-in-cpython-3-6) ;) – sethmlarson Jan 03 '17 at 15:23
  • 1
    There's a confusion here. This answer is **wrong** and shouldn't be the accepted answer. The hooks dictionary maps **blueprints** to an **ordered list of hook functions**. It doesn't map the hook functions directly. Global app hooks are stored as a list, into the `None` key of the `after_request_funcs` dictionary. According to the implementation, `after_request` hooks are executed in reversed declaration order, just as noticed by the OP. This contrasts with `before_request` hooks which are executed in order of declaration. See my answer for details. – user8808265 Feb 27 '19 at 16:11