Skip to content

Middleware.use() / Router.use() global middleware is never run by the dispatcher #55

@justin-k-bruce

Description

@justin-k-bruce

Summary: Middleware.use() / Router.use() register a global middleware class into _global_middleware, but the request dispatcher never reads that list — it iterates only each route's own middleware. So globally-registered middleware silently never runs. Severity: high (a documented API that does nothing).

Version: tina4-python 3.13.37.

Where

Registration — tina4_python/core/middleware.py (~29–53):

class Middleware:
    _global_middleware: list = []
    @classmethod
    def use(cls, middleware_class) -> None:
        if middleware_class not in cls._global_middleware:
            cls._global_middleware.append(middleware_class)
    @classmethod
    def get_global(cls) -> list: ...

Dispatch — tina4_python/core/server.py::_run_before_middleware() (~1250–1260) and _run_after_middleware() (~1284):

for _mw_cls in route.get("middleware", []):     # <-- ONLY route-level; globals ignored
    ...

Neither consults Middleware.get_global() / _global_middleware.

Impact

Apps that want app-wide middleware (tenant resolution, auth) can't use the documented Middleware.use() — we had to monkey-patch Router.add to prepend our middleware to every route's list.

Repro / regression test

from tina4_python.core.middleware import Middleware
ran = []
class Probe:
    @staticmethod
    def before_probe(req, resp):
        ran.append(1); return req, resp
Middleware.use(Probe)
# register a plain route with NO per-route middleware, dispatch a request to it, then:
assert ran, "Middleware.use() global was never invoked"

ran is empty today; populated after the fix.

Suggested fix

Prepend the registered globals in the dispatcher (mirror in _run_after_middleware):

for _mw_cls in Middleware.get_global() + list(route.get("middleware", [])):
    ...

or merge Middleware.get_global() into each route's middleware once in Router.add.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions