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

2025-01-17 09:23:00
admin
原创
103
摘要:问题描述:我正在为 Discord 制作一个 rick roll 网站,我想重定向到404响应状态代码上的 rick roll 页面。我尝试了以下操作,但没有效果: @app.exception_handler(fastapi.HTTPException) async def http_exception_...

问题描述:

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

我尝试了以下操作,但没有效果:

 @app.exception_handler(fastapi.HTTPException)
 async def http_exception_handler(request, exc):
     ...

解决方案 1:

更新

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

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')

或者,exception_handlers像这样使用 FastAPI 类的参数:

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)

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

工作示例

应用程序

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)

模板/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>

模板/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>

原始答案

您需要创建一个middleware并检查的status_coderesponse如果是404,则返回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

解决方案 2:

from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
from starlette.exceptions import HTTPException

# --- Constants --- #

templates = Jinja2Templates(directory="./templates")

# --- Error handler --- #

def lost_page(request, exception):
    headers = {"Content-Type": "text/html"}

    if isinstance(exception, HTTPException):
        status_code = exception.status_code
        detail = exception.detail
    elif isinstance(exception, Exception):
        status_code = 500
        detail = "Server Error"
        headers["X-Error-Message"] = exception.__class__.__name__
        headers["X-Error-Line"] = str(exception.__traceback__.tb_lineno)
    else:
        status_code = 500
        detail = f"Server Error

Details: {exception}"

    return templates.TemplateResponse(
        "404.html",
        {"request": request, "status_code": status_code, "detail": detail},
        status_code=status_code,
        headers=headers,
    )


exception_handlers = {num: lost_page for num in range(400, 599)}
app = FastAPI(exception_handlers=exception_handlers)

这是我在几个项目中使用过的一段代码,它本质上是所有 400 和 500 状态代码的汇总。

from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
from starlette.exceptions import HTTPException

# --- Constants --- #

templates = Jinja2Templates(directory="./templates")

此块导入相关库并初始化 Jinja2Templates,这使我们能够使用 FastAPI 呈现 HTML。文档。

让我们剖析一下

def lost_page(request, exception):
    headers = {"Content-Type": "text/html"}

    if isinstance(exception, HTTPException):
        status_code = exception.status_code
        detail = exception.detail
    elif isinstance(exception, Exception):
        status_code = 500
        detail = "Server Error"
        headers["X-Error-Message"] = exception.__class__.__name__
        headers["X-Error-Line"] = str(exception.__traceback__.tb_lineno)
    else:
        status_code = 500
        detail = f"Server Error

Details: {exception}"

    return templates.TemplateResponse(
        "404.html",
        {"request": request, "status_code": status_code, "detail": detail},
        status_code=status_code,
        headers=headers,
    )

FastAPI 的异常处理程序提供两个参数,导致异常的请求对象和引发的异常。

def lost_page(request, exception):

^^我们的函数采用这两个参数。

headers = {"Content-Type": "text/html"}

这些是我们将与请求一起发回的标题。

    if isinstance(exception, HTTPException):
        status_code = exception.status_code
        detail = exception.detail

    elif isinstance(exception, Exception):
        status_code = 500
        detail = "Server Error"
        headers["X-Error-Name"] = exception.__class__.__name__

    else:
        status_code = 500
        detail = f"Server Error

Details: {exception}"

如果exception参数是 HTTPException(由 Starlette/FastAPI 引发),那么我们将适当地设置 status_code 和详细信息。HTTPException 的一个示例是 404 错误,如果您尝试访问不存在的端点,则会引发 HTTPException 并由 FastAPI 自动处理。

然后,我们检查它是否是 的一个实例Exception,它是 Python 内置的异常类之一。这涵盖了诸如 、 等异常ZeroDivisionErrorFileNotFoundError这通常意味着我们的代码存在问题,例如尝试打开不存在的文件、除以零、使用未知属性或其他引发了未在端点函数内部处理的异常的情况。

else无论如何,这种阻止都不会被触发,并且可以被移除,这只是我为了安抚自己的良心而保留的东西。

status_code设置、和 标头后detail

    return templates.TemplateResponse(
        "404.html",
        {"request": request, "status_code": status_code, "detail": detail},
        status_code=status_code,
        headers=headers,
    )

我们返回 404 模板,TemplateResponse 函数接受几个参数,"404.html"即我们想要返回的文件、{"request": request, "status_code": status_code, "detail": detail}请求对象和我们想要填充的嵌入值(嵌入是在 jinja2 和 Python 之间传递信息的一种方式)。然后我们定义响应的状态代码及其标头。

这是我与错误处理程序一起使用的 404 html 模板。

exception_handlers = {num: lost_page for num in range(400, 599)}
app = FastAPI(exception_handlers=exception_handlers)

异常处理程序使用字典理解来创建状态代码词典以及应调用的函数,

exception_handlers = {400: lost_page, 401: lost_page, 402: lost_page, ...}

理解之后的样子是这样的,直到 599。

FastAPI 允许我们将此字典作为类的参数传递FastAPI

app = FastAPI(exception_handlers=exception_handlers)

这告诉 FastAPI 当端点函数返回特定状态代码时运行以下函数。

总而言之,上面的代码片段和这个错误模板应该可以帮助您以一种良好、用户友好和干净的方式处理所有 FastAPI 错误。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2974  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1836  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与管理过程中扮演着至关重要的角色。然而,在实际运行中,资源冲突是经常会遇到的难题。资源冲突可能导致项目进度延迟、成本增加以及产品质量下降等一系列问题,严重影响企业的效益与竞争力。因此,如何有效应对PLM系统中的资源冲突,成为众多企业关注的焦点。接下来,我们将详细探讨5...
plm项目管理系统   47  
  敏捷项目管理与产品生命周期管理(PLM)的融合,正成为企业在复杂多变的市场环境中提升研发效率、增强竞争力的关键举措。随着技术的飞速发展和市场需求的快速更迭,传统的研发流程面临着诸多挑战,而将敏捷项目管理理念融入PLM,有望在2025年实现研发流程的深度优化,为企业创造更大的价值。理解敏捷项目管理与PLM的核心概念敏捷项...
plm项目   47  
  模块化设计在现代产品开发中扮演着至关重要的角色,它能够提升产品开发效率、降低成本、增强产品的可维护性与可扩展性。而产品生命周期管理(PLM)系统作为整合产品全生命周期信息的关键平台,对模块化设计有着强大的支持能力。随着技术的不断发展,到 2025 年,PLM 系统在支持模块化设计方面将有一系列令人瞩目的技术实践。数字化...
plm软件   48  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用