异常
Starlette 允许您安装自定义异常处理程序,以处理在发生错误或已处理的异常时如何返回响应。
from starlette.applications import Starlette
from starlette.exceptions import HTTPException
from starlette.requests import Request
from starlette.responses import HTMLResponse
HTML_404_PAGE = ...
HTML_500_PAGE = ...
async def not_found(request: Request, exc: HTTPException):
return HTMLResponse(content=HTML_404_PAGE, status_code=exc.status_code)
async def server_error(request: Request, exc: HTTPException):
return HTMLResponse(content=HTML_500_PAGE, status_code=exc.status_code)
exception_handlers = {
404: not_found,
500: server_error
}
app = Starlette(routes=routes, exception_handlers=exception_handlers)
如果 debug
已启用且发生错误,则 Starlette 将使用回溯响应,而不是使用已安装的 500 处理程序。
app = Starlette(debug=True, routes=routes, exception_handlers=exception_handlers)
除了为特定的状态码注册处理程序外,您还可以为异常类注册处理程序。
特别是您可能想要覆盖内置的 HTTPException
类的处理方式。例如,使用 JSON 风格的响应:
async def http_exception(request: Request, exc: HTTPException):
return JSONResponse({"detail": exc.detail}, status_code=exc.status_code)
exception_handlers = {
HTTPException: http_exception
}
HTTPException
还配备了 headers
参数。这允许将标头传播到响应类:
async def http_exception(request: Request, exc: HTTPException):
return JSONResponse(
{"detail": exc.detail},
status_code=exc.status_code,
headers=exc.headers
)
您可能还想要覆盖 WebSocketException
的处理方式:
async def websocket_exception(websocket: WebSocket, exc: WebSocketException):
await websocket.close(code=1008)
exception_handlers = {
WebSocketException: websocket_exception
}
错误和已处理的异常
区分已处理的异常和错误是很重要的。
已处理的异常并不代表错误情况。它们被强制转换为适当的 HTTP 响应,然后通过标准中间件栈发送。默认情况下,使用 HTTPException
类来管理任何已处理的异常。
错误是应用程序内发生的任何其他异常。这些情况应作为异常在整个中间件堆栈中冒泡。任何错误日志记录中间件都应确保将异常一路重新引发到服务器。
实际上,所使用的错误处理为 exception_handler[500]
或 exception_handler[Exception]
。 500
和 Exception
这两个键均可使用。见下文:
async def handle_error(request: Request, exc: HTTPException):
# Perform some logic
return JSONResponse({"detail": exc.detail}, status_code=exc.status_code)
exception_handlers = {
Exception: handle_error # or "500: handle_error"
}
需要注意的是,如果 BackgroundTask
引发异常,将由 handle_error
函数进行处理,但此时响应已经发送。换句话说, handle_error
创建的响应将被丢弃。如果错误发生在响应发送之前,那么将使用响应对象 - 在上述示例中,为返回的 JSONResponse
。
为了正确处理这种行为, Starlette
应用程序的中间件堆栈是这样配置的:
ServerErrorMiddleware
- 当服务器出现错误时返回 500 个响应。- 已安装的中间件
ExceptionMiddleware
- 处理已处理的异常,并返回响应。- 路由器
- 端点
HTTP 异常
HTTPException
类提供了一个基类,您可以将其用于任何已处理的异常。 ExceptionMiddleware
的实现默认对于任何 HTTPException
都返回纯文本 HTTP 响应。
HTTPException(status_code, detail=None, headers=None)
您应该仅在路由或端点内部引发 HTTPException
。相反,中间件类应该直接返回适当的响应。
WebSocket 异常
您可以使用 WebSocketException
类在 WebSocket 端点内部引发错误。
WebSocketException(code=1008, reason=None)
您可以设置规范中定义的任何有效代码。