Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 982
Mangu Singh Rajpurohit Avatar asked Mar 19 '18 14:03

Mangu Singh Rajpurohit


People also ask

Which of the following middleware are executed during the response phase?

In Django, middleware is a lightweight plugin that processes during request and response execution. Middleware is used to perform a function in the application.

How does Django implement middleware?

To activate a middleware component, add it to the MIDDLEWARE list in your Django settings. A Django installation doesn't require any middleware — MIDDLEWARE can be empty, if you'd like — but it's strongly suggested that you at least use CommonMiddleware .

What is the nature of middleware in terms of usage in Django?

Middleware is a framework of hooks into Django's request/response processing. It's a light, low-level “plugin” system for globally altering Django's input or output. Each middleware component is responsible for doing some specific function.

What is middleware in Django Geeksforgeeks?

Middleware is like a middle ground between a request and response. It is like a window through which data passes. As in a window, light passes in and out of the house. Similarly, when a request is made it moves through middlewares to views, and data is passed through middleware as a response.


1 Answers

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.

like image 94
Han Avatar answered Oct 25 '22 21:10

Han