Exceptions & Exception Handlers¶
Exception handlers are, as the name suggests, the handlers in case an exception of type X occurs.
Exception handlers¶
In every level the exception_handler
parameter (among others) are available to be used and handle specific exeptions
raised on each level.
The exception handlers are in read a python dictionary and you can pass the key as the exception itself or the status_code
that will always use the exception itself.
from json import loads
from lilya import status
from lilya.apps import Lilya
from lilya.requests import Request
from lilya.responses import JSONResponse
from lilya.routing import Include, Path
async def handle_type_error(request: Request, exc: TypeError):
status_code = status.HTTP_400_BAD_REQUEST
details = loads(exc.json()) if hasattr(exc, "json") else exc.args[0]
return JSONResponse({"detail": details}, status_code=status_code)
async def handle_value_error(request: Request, exc: ValueError):
status_code = status.HTTP_400_BAD_REQUEST
details = loads(exc.json()) if hasattr(exc, "json") else exc.args[0]
return JSONResponse({"detail": details}, status_code=status_code)
async def me():
return "Hello, world!"
app = Lilya(
routes=[
Include(
"/",
routes=[
Path(
"/me",
handler=me,
)
],
)
],
exception_handlers={
TypeError: handle_type_error,
ValueError: handle_value_error,
},
)
What is happening¶
The application level contains an exception handler handle_type_error
and the handle_value_error
and that means that for
every HTTPException
and ValueError
being raised in the application it will be handled by that function.
Custom exception handlers¶
We all know that Lilya handles really well the exceptions by design but sometimes we might also
want to throw an error while doing some code logic that is not directly related with a data
of
an handler.
Example
from lilya.apps import Lilya
from lilya.requests import Request
from lilya.routing import Path
async def create(request: Request):
data = await request.json()
if len(data) == 0:
raise ValueError("Cannot be 0.")
app = Lilya(
routes=[
Path(
"/create",
handler=create,
methods=["POST"],
)
],
)
This example is a not usual at all but it serves to show where an exception is raised.
Lilya offers one out of the box custom exception handlers:
- handle_value_error - When you want the
ValueError
exception to be automatically parsed into a JSON.
from lilya._internal._exception_handlers import handle_value_error
How it would look like the previous example using this custom exception handler?
from lilya._internal._exception_handlers import handle_value_error
from lilya.apps import Lilya
from lilya.requests import Request
from lilya.routing import Path
async def create(request: Request):
data = await request.json()
if len(data) == 0:
raise ValueError("Cannot be 0.")
app = Lilya(
routes=[Path("/create", handler=create)],
exception_handlers={
ValueError: handle_value_error,
},
)
Using status codes¶
When declaring exception handlers, as mentioned before, you can use status codes instead of the
exception itself. This allows and indicates how an exception must be handle when a specific status_code
occurs.
This can be very useful if you only want to narrow down to status_code
approach instead of the whole
Exception
itself.
from lilya.apps import Lilya
from lilya.exceptions import HTTPException
from lilya.requests import Request
from lilya.responses import Error
async def not_found(request: Request, exc: HTTPException):
return Error("Oops", status_code=exc.status_code)
async def server_error(request: Request, exc: HTTPException):
return Error("Oops", status_code=exc.status_code)
app = Lilya(
routes=...,
exception_handlers={
404: not_found,
500: server_error,
},
)
HTTPException¶
The HTTPException
class serves as a foundational class suitable for handling various exceptions.
In the default ExceptionMiddleware
implementation, plain-text HTTP responses are returned for any instance of HTTPException
.
Note
The proper usage dictates that you exclusively raise HTTPException
within routing or endpoints.
Middleware and Permission classes, on the other hand, should simply return the appropriate responses directly.
WebSocketException¶
The WebSocketException
class is designed for raising errors specifically within WebSocket endpoints.