Looks like both of answers are outdated.
Now (python 3.12 + aiohttp 3.10.9) it may be simply done with middleware:
from aiohttp import web, web_exceptions
from typing import Callable
# here is our middleware that will handle all errors including 404
# and rewrite responses
@web.middleware
async def custom_error_handling_middleware(request: web.Request, handler: Callable):
try:
resp: web.Response = await handler(request)
# here we are catching aiohttp related exception
except web_exceptions.HTTPException as e:
# since HTTPException childs are response-ready it may be return as response later
resp = e
# if status code of our exception is 404
# we will sutomize it as we want (update body and headers in my case)
if resp.status_code == web_exceptions.HTTPNotFound.status_code:
resp.text = '<html><body><code>How did you find me? ≧☉_☉≦</code></body></html>'
resp.content_type = 'text/html'
resp.charset = 'utf-8'
# here we are generating custom page for a specific non aiohttp related exception
# (didn't asked in the question but added as bonus)
except ZeroDivisionError:
resp = web_exceptions.HTTPInternalServerError(
text='<html><body><code>Mamma mia! (╯`Д´)╯︵ ┻━┻</code></body></html>',
content_type = 'text/html',
)
# here we are generating custom page for any unexpected exception
# (didn't asked in the question but added as bonus)
except Exception as e:
resp = web_exceptions.HTTPInternalServerError(
text='<html><body><code>Completely unexpected error ¯\\(°_o)/¯</code></body></html>',
content_type='text/html',
)
return resp
# correct view
async def hello(_: web.Request):
return web.Response(
text = '<html><body><code>Hello world ( っ˶´ ˘ `)っ</code></body></html>',
content_type='text/html',
charset='utf-8',
)
# view that will respond an expected error
async def divizion_error(_: web.Request):
1/0
return web.Response(text='response will never happen')
# view that will respond an unexpected error
async def unexpected_error(_: web.Request):
return web.Response(text=unbound_variable_for_example)
# standard functions to make and run a demo app
async def create_app():
app = web.Application(middlewares=[custom_error_handling_middleware])
app.add_routes([
web.get("/div", divizion_error, name='divizion_error_view'),
web.get("/unex", unexpected_error, name='unexpected_500_view'),
web.get("/", hello, name='only_existant_view'),
])
return app
if __name__ == '__main__':
app = create_app()
web.run_app(app, port=8888)
After adding the custom_error_handling_middleware, How did you find me will be shown as standard 404 page