11from __future__ import annotations
22
33import abc
4+ import warnings
45from abc import abstractmethod
56from typing import TYPE_CHECKING , Any , Callable , Protocol , runtime_checkable
67
78from litestar .enums import ScopeType
89from litestar .middleware ._utils import (
910 build_exclude_path_pattern ,
11+ should_bypass_for_path_pattern ,
1012 should_bypass_middleware ,
1113)
1214from litestar .utils .deprecation import warn_deprecation
@@ -230,13 +232,6 @@ async def handle(
230232 Applied to a route with a dynamic path like ``/static/{file_name:str}``, it would
231233 be skipped *only* if ``file_name`` has a ``.jpg`` extension.
232234
233- .. note::
234-
235- If it is not required to dynamically match the path of a request,
236- :attr:`~litestar.middleware.ASGIMiddleware.exclude_path_pattern` should be
237- used instead. Since its exclusion is done statically at startup time, it has no
238- performance cost at runtime.
239-
240235 .. versionadded:: 2.19
241236 """
242237
@@ -246,16 +241,46 @@ def __call__(self, app: ASGIApp) -> ASGIApp:
246241 exclude_pattern = build_exclude_path_pattern (exclude = self .exclude_path_pattern , middleware_cls = type (self ))
247242 scopes = set (self .scopes )
248243 exclude_opt_key = self .exclude_opt_key
244+ should_bypass_for_scope = self .should_bypass_for_scope
245+
246+ def exclude_pattern_matches_handler_path (scope : Scope ) -> bool :
247+ handler = scope ["route_handler" ]
248+ return any (exclude_pattern .search (path ) for path in handler .paths )
249249
250250 async def middleware (scope : Scope , receive : Receive , send : Send ) -> None :
251- if should_bypass_middleware (
252- scope = scope ,
253- scopes = scopes , # type: ignore[arg-type]
254- exclude_opt_key = exclude_opt_key ,
255- exclude_path_pattern = exclude_pattern ,
251+ path_excluded = False
252+ if (
253+ should_bypass_middleware (
254+ scope = scope ,
255+ scopes = scopes , # type: ignore[arg-type]
256+ exclude_opt_key = exclude_opt_key ,
257+ )
258+ or (path_excluded := should_bypass_for_path_pattern (scope , exclude_pattern ))
259+ or (should_bypass_for_scope and should_bypass_for_scope (scope ))
256260 ):
261+ if path_excluded and exclude_pattern is not None and not exclude_pattern_matches_handler_path (scope ):
262+ warnings .warn (
263+ f"{ type (self ).__name__ } .exclude_path_pattern={ exclude_pattern .pattern !r} "
264+ "did match the request path but did not match the route "
265+ "handler's path. When upgrading to Litestar 3, this middleware "
266+ "would NOT be excluded. To keep the current behaviour, use "
267+ "'should_bypass_for_scope' instead." ,
268+ category = DeprecationWarning ,
269+ stacklevel = 2 ,
270+ )
271+
257272 await app (scope , receive , send )
258273 else :
274+ if exclude_pattern is not None and exclude_pattern_matches_handler_path (scope ):
275+ warnings .warn (
276+ f"{ type (self ).__name__ } .exclude_path_pattern={ exclude_pattern .pattern !r} "
277+ "did not match the request path but did match the route "
278+ "handler's path. When upgrading to Litestar 3, this middleware "
279+ "would be excluded. To keep the current behaviour, use "
280+ "'should_bypass_for_scope' instead." ,
281+ category = DeprecationWarning ,
282+ stacklevel = 2 ,
283+ )
259284 await handle (scope = scope , receive = receive , send = send , next_app = app )
260285
261286 return middleware
0 commit comments