文档处理程序和错误

错误页面

失败的请求仍应像站点的其余部分一样进行响应:对于访问者来说,是一个用您自己的话表示的页面,与 API 客户端的 JSON 失败相同。 Nexy 回答了这两个问题,并用一个文件替换每个答案。

此页面是地图:哪个文件回答哪个状态,以及如何制作您的第一个。文件夹的页面有它们自己的页面。

一次失败,两种答案

谁回答失败的请求
a request that fails
      │
      ├── a browser (Accept: text/html)              ──►  an HTML page
      └── an API client (Accept: application/json)   ──►  {"detail": "…"}  with the same status

the HTML page
      ├── the deepest folder of the URL that holds a file   ──►  your file
      └── no folder of the chain holds one                 ──►  the built-in page

您的第一页

创建 src/routes/notfound.nexy 并写入访问者应该阅读的内容:

src/routes/notfound.nexy
---metadata = {"title": "Page not found"}---<h1>Page not found</h1><p>The page moved or never existed. <a href="/">Back home</a>.</p>

保存并请求 URL,但没有任何服务:

curl -i -H "Accept: text/html" http://localhost:3000/nowhere# HTTP/1.1 404 Not Found

路由根目录下的文件回答了整个项目;文件夹中的副本仅响应该文件夹并保持其余部分不变。无需任何文件,Nexy 即可提供其内置样式页面。

哪个文件回答

文件 答案
notfound.nexy 404 为其目录
errors.nexy 500 为其目录
forbidden.nexy 403 为其目录
unauthorized.nexy 401 为其目录
loading.nexy 保留;还没有运行时效果
情况 回答
没有路线匹配 404
动态段无法转换为其注释 404
页面或 API 处理程序中未处理的异常 500
raise HTTPException(status_code=403) 您提出的状态,HTML 或 JSON 格式
notFound(),forbidden(),unauthorized() 404、403、401,来自请求中的任何位置
redirect(),permanentRedirect() 真正的重定向,没有错误页面

通过代码留下页面或答案

redirect、permanentRedirect、notFound、forbidden 和 unauthorized 引发 HTTP 异常,因此相同的调用在 .nexy 页面、API 处理程序、模块化控制器、防护和 dependencies.py 中工作。它们在客户端上具有相同的名称 (@nexy/client)。

src/routes/posts/[slug].nexy
---from nexy import notFound, redirect from src.posts import find slug: prop[str]post = find(slug)if post is None:    notFound()if post.moved_to:    redirect(post.moved_to)---<h1>{{ post.title }}</h1>
致电 回答
redirect(url) 307; redirect(url, status=303) 将表单后的 POST 转换为 GET
permanentRedirect(url) 308;浏览器和搜索引擎会记住它
notFound(detail=None) 404:notfound 页面,或 API 客户端的 JSON
forbidden(detail=None) 403:访问者是已知的,但可能看不到此内容
unauthorized(detail=None, scheme=None) 401; scheme="Bearer" 添加 WWW-Authenticate

重定向响应带有 Location 标头,但没有页面,也返回到 API 客户端。根据您信任的价值观构建目的地:redirect(request.query_params["next"]) 将访问者发送到链接所说的任何地方。带有换行符的目的地将被拒绝。

警卫保护整个文件夹:

src/routes/private/dependencies.py
from nexy import unauthorizedfrom nexy.http import Request  def require_login(request: Request) -> None:    if not request.session.get("user"):        unauthorized(scheme="Bearer")  dependencies = [require_login]

HTML 或 JSON

对于相同的异常,不同的提问者会给出不同的答案:

  • 浏览器 (Accept: text/html) 获取 HTML 页面。详细信息是 HTML 转义的,因此根据用户输入构建的消息无法注入标记。
  • 请求 JSON 而不是页面 (Accept: application/json) 的客户端会获得具有相同状态代码的 {"detail": "..."}。
src/routes/api/items/[id].py
from nexy.http import HTTPException  async def GET(id: int):    if id > 100:        raise HTTPException(status_code=403, detail="Out of range")    return {"id": id}
curl -H "Accept: application/json" http://localhost:3000/api/items/500# {"detail":"Out of range"}

未处理的异常

没有任何处理的异常会被记录一次,除了异常的来源和周围的代码,并根据模式进行回答。

nx dev nx start
浏览器 包含错误的页面、引发错误的代码行以及完整的回溯 带有参考的内置 500 页面(或您的 errors.nexy)
JSON客户端 {"detail", "reference", "error"} {"detail", "reference"}
服务器日志 异常和代码行 异常和整个回溯,具有相同的引用
  x ZeroDivisionError: division by zero  GET /boom  ref fe6a5217    at src/routes/boom.py:2 in GET       1 | def GET():       2 |     return {"a": 1 / 0}

参考号是八个字符,每次失败都是新的。访问者可以引用它,您可以通过在日志中搜索它来找到回溯。异常和代码都不会到达生产中的访问者。自定义 errors.nexy 仅替换页面;日志行保留。

验证错误

对于每个客户端,缺少标头、查询参数或正文字段都会使用 FastAPI 的 JSON 正文回答 422。请参阅验证和错误。

后续步骤

在 GitHub 上编辑

Enter 打开结果,Esc 关闭。