Middleware Flow

Deep dive into the request/response middleware processing pipeline

Middleware Flow

This document details the middleware pipeline in the crelio-app service, explaining how requests are processed, authenticated, and enriched before reaching the view layer.

Overview

The middleware stack is configured in config/settings/base.py. Request processing flows down through the list, while response processing flows up.


Standard vs Custom Middlewares

MiddlewareTypeResponsibility
SecurityMiddlewareStandardHTTP security headers (HSTS, XSS protection)
SessionMiddlewareStandardHydrates request.session from cookies
CorsMiddleware3rd PartyHandles Cross-Origin Resource Sharing headers
UserAgentMiddleware3rd PartyParses user agent string
ErrorReportingMiddlewareCustomGlobal exception handling and reporting
AuthenticationMiddlewareCustomMulti-tenant authentication and user context
StoreIdentifierMiddlewareCustomE-commerce store context resolution
ThreadingLocaleMiddlewareCustomThread-local persistence of request/session

Detailed Request Flow

The following sequence diagram illustrates the deep logic within the custom middlewares.


Deep Dive: Custom Middlewares

1. ErrorReportingMiddleware

Location: core/middlewares/error_reporting.py

Functions as the safety net for the application. It sits high in the stack to catch exceptions from all subsequent layers.

  • Process:
    • Catches ALL unhandled exceptions.
    • Ignores specific benign errors (ValidationError, ShippingError).
    • Reports to Sentry with tags (app, is_mobile).
    • Returns a standardized JSON response instead of Django's HTML debug page.
def process_exception(self, request, err):
    status_code, response = self.report_exception(request, err)
    return JsonResponse(response, status=status_code or 500)

2. AuthenticationMiddleware

Location: core/middlewares/authentication.py

The core security gatekeeper. It supports multiple authentication strategies based on the incoming request type.

  • Request Classification:

    • is_mobile: Requests from mobile apps (uses JWT).
    • is_pacs_request: Internal PACS service communication.
    • is_lambda_request: AWS Lambda callbacks.
    • is_internal_request: Internal microservice calls.
    • is_web: Browser-based session requests.
  • User Type Resolution (Web):

    • Determines if the user is a labuser (staff), patient, or supportuser based on URL patterns and session data.
    • Dispatches to specialized authenticators:
      • authenticate_labuser
      • authenticate_patient
      • authenticate_supportuser
  • Response Enrichment:

    • Sets global cookies: DEPLOYMENT_ZONE, DEPLOYMENT_MODE.
    • Injects translation updates if needed.

3. StoreIdentifierMiddleware

Location: crm/store/middleware.py

Handles context for the e-commerce and patient portal features.

  • Logic:
    • Inspects request.get_host() (Domain).
    • Resolves store_uuid using domain_identifier utility.
    • If a white-label domain is detected, sets white_labeled_lab_id.
    • Injects store_uuid directly into view_kwargs so views don't need to look it up.
    • Manages storeId cookies to persist store selection across sessions.

4. ThreadingLocaleMiddleware

Location: core/middlewares/local.py

Solves the problem of accessing request.session in deep utility layers where request object isn't available.

  • Mechanism:
    • Uses python's threading.local() to create thread-safe storage.
    • Saves request.session at start of request.
    • Clears it at end of request to prevent memory leaks or data pollution.
    • Usage: Used by ActivityLog and other audit utilities to get the current user ID without passing request through every function signature.

Critical Logic Paths

Authentication Bypass

  • URL patterns defined in guest_methods decorator or views marked with authentication_classes = [] in DRF are NOT skipped by this middleware.
  • Instead, the middleware checks resolve(request.path).view_name in guest_methods.
  • Warning: If a view is public, it must be explicitly marked.

Exception Handling

  • ValidationError is treated as a logic error, not a system crash. It returns 400 (or custom status) and is NOT reported to Sentry.
  • Ratelimited exceptions return 429 Too Many Requests.

On this page