.. _middlewares: Middlewares =========== Description ----------- Middleware functions in **Django** allow you to process requests and responses globally before they reach the view or after they leave the view. Middlewares in DSG are made to be compatible with **Django** ones for most cases, the difference is the argument being of type :func:`django_socio_grpc.request_transformer.GRPCRequestContainer` For more information see `Django documentation `_. To use a middleware, you need to add it to the :ref:`GRPC_MIDDLEWARE` list in your :ref:`DSG Settings `. The order of the middleware is important, as they will be executed in order. Available Middlewares --------------------- ========================================================================================================= :func:`close_old_connections_middleware ` ========================================================================================================= - This middleware is responsible for closing old database connections at the beginning and end of a request/response cycle. - It resets database queries and ensures that unused database connections are closed. .. _middlewares-log-requests-middleware: ======================================================================================= :func:`log_requests_middleware ` ======================================================================================= - This middleware logs information about incoming gRPC requests. - It logs the service action being called unless it's listed in the :ref:`grpc_settings.IGNORE_LOG_FOR_ACTION` setting. =========================================================================== :func:`locale_middleware ` =========================================================================== - This middleware sets the language for the current request based on the request context. - It is used to replace `Django local middleware `_ - It activates the translation engine with the detected language. ======================================================================================================= :func:`auth_without_session_middleware ` ======================================================================================================= - This middleware is used to replace the default `Django Authentication Middleware `_ when using authentication patterns other than session-based authentication (e.g., Token-based). - It calls the :func:`perform_authentication` method of the gRPC service to perform authentication. - It should be placed **before any other middleware** that depends on the ``context.user`` attribute. Each middleware function follows a similar pattern, where it performs its specific task and then passes the request/response further down the middleware stack using get_response. The choice between synchronous and asynchronous execution depends on whether get_response is synchronous or asynchronous. These middleware functions provide custom behavior for gRPC requests and responses in the Django application. Example ------- The following example already exist in DSG but it here to help you understand how to create your own. It's recommended to create them in a created ``my_app.middlewares.py`` file. Then you can use them with the :ref:`GRPC_MIDDLEWARE` settings. Source code for the :func:`locale_middleware ` middleware: .. code-block:: python import asyncio from typing import Callable from django.utils import translation from django.utils.decorators import sync_and_async_middleware from django_socio_grpc.services.servicer_proxy import GRPCRequestContainer from django_socio_grpc.utils.utils import safe_async_response # This decorator declares the middleware as supporting # both synchronous and asynchronous requests. @sync_and_async_middleware # get_response is the next middleware (or the actual GRPCAction if last) def locale_middleware(get_response: Callable): # As it is supporting both synchronous and asynchronous requests, # it returns a sync or async function depending on the type of get_response. if asyncio.iscoroutinefunction(get_response): async def middleware(request: GRPCRequestContainer): language = translation.get_language_from_request(request.context) translation.activate(language) # `django_socio_grpc.utils.utils.safe_async_response` # is a utility function that wraps the response in a coroutine. # The response could be a coroutine or an async generator # so we need to wrap it in a coroutine to be able to await it. return await safe_async_response(get_response, request) else: def middleware(request: GRPCRequestContainer): language = translation.get_language_from_request(request.context) translation.activate(language) return get_response(request) return middleware