Package: aiohttp-route-middleware
aiohttp-routed-middlewareOverviewAn extension foraiohttpwhich provides route local middleware while remainining compatible with the existing router.With the built in router the technique for managing route local middleware is to make nested applications.
However nested applications require a unique url prefix. so the following cannot be achieved:RequestMiddlewareHandlerGET /post/{id}authenticate, authorise(['post:read'])get_postPOST /post/{id}authenticate, authorise(['post:read:', 'post:write'])create_postDELETE /post/{id}authenticate, authorise(['post:read:', 'post:write'])delete_postThis router allows a chain of middleware terminated by a handler. For example:post_app=web.Application(router=UrlDispatcherEx())post_app.router.add_get('/{id}',authenticate,authorise(['post:read']),get_posts)post_app.router.add_post('/{id}',authenticate,authorise(['post:read','post:write']),get_posts)post_app.router.add_delete('/{id}',authenticate,authorise(['post:read','post:write']),get_posts)app=web.Application()app.add_subapp('/post',post_app)UsageBasicA middleware function differs from a normal request handler, in that it gets given the next handler to call.The following example shows how to add middleware to a route.fromaiohttpimportwebfromaiohttp_route_middlewareimportUrlDispatcherExapp=web.Application(router=UrlDispatcherEx())app.router.add_get('/',middleware1,middleware2,test)asyncdeftest(request):print("..entering handler")response=web.Response(text=f"extra_stuff=[{', '.join(request.extra_stuff)}]")print("..exiting handler")returnresponse@web.middlewareasyncdefmiddleware1(request,handler):print("entering middleware 1")request.extra_stuff=['foo']response=awaithandler(request)print("exiting middleware 1")returnresponse@web.middlewareasyncdefmiddleware2(request,handler):print(".entering middleware 2")request.extra_stuff.append('bar')response=awaithandler(request)print(".exiting middleware 2")returnresponseapp=web.Application(router=UrlDispatcherEx())app.router.add_get('/',middleware1,middleware2,test)web.run_app(app)This would print out the following:enteringmiddleware1.enteringmiddleware2..enteringhandler
..exitinghandler
.exitingmiddleware2exitingmiddleware1Middleware failureA middleware function may choose not to call the next handler; for example if there was an authentication error.fromaiohttpimportwebfromaiohttp_route_middlewareimportUrlDispatcherExasyncdeftest(request):returnweb.Response(text="Success")@web.middlewareasyncdefauthenticate(request,handler):returnweb.Response(body="unauthenticated",status=401)app=web.Application(router=UrlDispatcherEx())app.router.add_get('/',authenticate,test)web.run_app(app)InstallationYou can install it using pip:pipinstallaiohttp-route-middlewareDetailsThe extension provides a routerUrlDispatcherExwhich extends from the built in classUrlDispatcher. The class can be used in the following manner:fromaiohttp_route_middlewareimportUrlDispatcherEx...app=web.Application(router=UrlDispatcherEx())The extension allows multiple handlers to be specified. The handlers are called in order until a handler returns a nonNoneresponse, at which point the response is returned and execution stops.An example of this might be a route to update a comment on a post, The sequence might be:Authenticate the user.Check the user is authorised to post a comment.Fetch the post.Post the comment.app.router.add_post('/comment?post_id=1234',authenticate,authorise,fetch_post,post_comment)Each handler is written in the same manner as a normal handler, in that it takes a single request argument. The request argument may be modified or enriched by each handler.