Description
Long story short
With my custom authentication, trying to have an authentication middleware that requires login by default, except for the handlers specifically annotated with a decorator.
def login_exempt(func: F) -> F:
func.weblogin_login_exempt = True # type: ignore
return func
@web.middleware
async def auth_middleware(
request: web.Request,
handler: Callable[[web.Request], Awaitable[web.StreamResponse]],
) -> web.StreamResponse:
print(handler, hasattr(handler, "weblogin_login_exempt"))
if not hasattr(handler, "weblogin_login_exempt"):
session = await weblogin.fetch_session(request)
if not session:
raise web.HTTPNotFound(
text=json.dumps(weblogin.SESSION_NOT_FOUND),
content_type="application/json",
)
return await handler(request)
def create_web_app() -> web.Application:
app = web.Application(
middlewares=[weblogin.session_middleware, auth_middleware]
)
app.on_startup.append(async_init)
app.on_shutdown.append(do_shutdown)
app.router.add_route("GET", "/healthz", healthz)
app.add_subapp("/s/weblogin", weblogin.create_web_app())
app.add_subapp("/s/userprefs", userprefs.create_web_app())Expected behaviour
I expect the handler to have weblogin_login_exempt when it has been decorator, causing the framework to skip the usual auth checks.
Actual behaviour
Instead, at least in the case of a subapp, the handler is a functools.partial(), which means the actual handler function is hidden away.
functools.partial(<function _fix_request_current_app.<locals>.impl at 0x7efbf9fb48c8>, handler=<function login at 0x7efbf9f7ba60>)
Only for the toplevel Application is the handler unmodified. For a subapp, handler is wrapped as a functools.partial() object.
In general, I am either missing something obvious, or there is a lack of an API in aiohttp to achieve this sort of thing. I would like to be able to annotate handlers, somehow, and for middleware to fetch the handler annotations.
Steps to reproduce
Your environment
aiohttp 3.6.1, python 37.3.