如何使用 FastAPI 返回自定义 404 Not Found 页面?

Ash*_*mPL 4 python exception http-status-code-404 starlette fastapi

我正在为 Discord 制作一个 rick roll 网站,我想重定向到404响应状态代码的 rick roll 页面。

我尝试了以下方法,但没有成功:

 @app.exception_handler(fastapi.HTTPException)
 async def http_exception_handler(request, exc):
     ...
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 6

更新

一个更优雅的解决方案是使用自定义异常处理程序,传递您想要处理的异常的状态代码,如下所示:

from fastapi.responses import RedirectResponse
from fastapi.exceptions import HTTPException

@app.exception_handler(404)
async def not_found_exception_handler(request: Request, exc: HTTPException):
    return RedirectResponse('https://fastapi.tiangolo.com')
Run Code Online (Sandbox Code Playgroud)

或者,使用exception_handlersFastAPI 类的参数,如下所示:

async def not_found_error(request: Request, exc: HTTPException):
    return RedirectResponse('https://fastapi.tiangolo.com')

exception_handlers = {404: not_found_error}
app = FastAPI(exception_handlers=exception_handlers)
Run Code Online (Sandbox Code Playgroud)

注意:在上面的示例中,RedirectResponse返回了 a,因为 OP 要求重定向用户。但是,您可以返回一些自定义Response,HTMLResponseJinja2 TemplateResponse,如下面的示例所示。

工作示例

应用程序.py

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.exceptions import HTTPException


async def not_found_error(request: Request, exc: HTTPException):
    return templates.TemplateResponse('404.html', {'request': request}, status_code=404)


async def internal_error(request: Request, exc: HTTPException):
    return templates.TemplateResponse('500.html', {'request': request}, status_code=500)

    
templates = Jinja2Templates(directory='templates')

exception_handlers = {
    404: not_found_error,
    500: internal_error
}

app = FastAPI(exception_handlers=exception_handlers)
Run Code Online (Sandbox Code Playgroud)

模板/404.html

<!DOCTYPE html>
<html>
   <title>Not Found</title>
   <body>
      <h1>Not Found</h1>
      <p>The requested resource was not found on this server.</p>
   </body>
</html>
Run Code Online (Sandbox Code Playgroud)

模板/500.html

<!DOCTYPE html>
<html>
   <title>Internal Server Error</title>
   <body>
      <h1>Internal Server Error</h1>
      <p>The server encountered an internal error or 
         misconfiguration and was unable to complete your request.
      </p>
   </body>
</html>
Run Code Online (Sandbox Code Playgroud)

原答案

您需要创建middleware并检查status_coderesponse。如果是404,则返回 a RedirectResponse。例子:

from fastapi import Request
from fastapi.responses import RedirectResponse

@app.middleware("http")
async def redirect_on_not_found(request: Request, call_next):
    response = await call_next(request)
    if response.status_code == 404:
        return RedirectResponse("https://fastapi.tiangolo.com")
    else:
        return response
Run Code Online (Sandbox Code Playgroud)