What's the sequence of middleware execution in django when error occurs in process_request?
Asked Answered
V

2

9

I am looking into django middleware codebase. I looked into following diagramenter image description here

So, the diagram is quite clear.

But I have some questions

  1. What happens when exception comes in process_request() middleware ? How is it handled ? Will the response_middleware be invoked ? Eg. if exception comes in process_view() of AuthenticationMiddleware, then will process_response() of MessageMiddleware be invoked ?

  2. What happens when in process_response() middleware returns response? Eg. if process_view() of AuthenticationMiddleware returns respones, then will process_response() of MessageMiddleware be invoked ? OR it'll turn back from AuthenticationMiddleware(ie, it'll invoke process_response() of AuthenticationMiddleware, but will not invoke process_response() of MessageMiddleware)

I have debugged the behaviour of django in 1.10 where new style middleware classes are used, but I am not familiar about old MIDDLEWARE_CLASSES settings ?

For django 1.10:- 1) If process_request() for AuthenticationMiddleware returns response, then process_template_response() and process_response() will be invoked as show in the figure given below for all the middlewares.

2) If process_request() for AuthenticationMiddleware raises exception, then also the behavior will be the same.

Correct me, If I am wrong.

Thanks in Advance.

Vivisection answered 19/3, 2018 at 14:46 Comment(0)
P
1

The official documentation could answer your first question if you work on django project before the version 1.10.

please read the paragraph : behavioral differences between using MIDDLEWARE and MIDDLEWARE_CLASSES

Under MIDDLEWARE_CLASSES, every middleware will always have its process_response method called, even if an earlier middleware short-circuited by returning a response from its process_request method. Under MIDDLEWARE, middleware behaves more like an onion: the layers that a response goes through on the way out are the same layers that saw the request on the way in. If a middleware short-circuits, only that middleware and the ones before it in MIDDLEWARE will see the response.

However MIDDLEWARE_CLASSES has been removed since django v1.10, and new style of middleware workflow (using __call__() instead) has been introduced since then, this allows each middleware (applied in MIDDLEWARE) to internally determine whether to short-circuit by returning response back (with error status) and not invoking subsequent middlewares and view middleware on exception handling, in such case, the diagram in the question may not be always the case, especially if your project includes custom middlewares.

[side note], a middleware with short-circuiting on exception may look like this :

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        try:
            # Code to be executed for each request before
            # the view (and later middleware) are called.
            do_something_but_raise_exception()
            response = self.get_response(request)
            # Code to be executed for each request/response after
            # the view is called.
        except WHATEVER_EXCEPTION as e:
            # short-circuiting, because self.get_response() is not invoked,
            response = generate_custom_response(e)
        return response

[Side note]:

For what it's worth , middlewares in FastAPI are also structured in similar way.

Plowman answered 25/11, 2020 at 6:49 Comment(0)
D
0

For 2), you are right. Function convert_exception_to_response() will catch the exceptions which process_request() raises.
See the source:
https://github.com/django/django/blob/master/django/core/handlers/base.py https://github.com/django/django/blob/master/django/core/handlers/exception.py

Debit answered 7/3, 2019 at 9:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.