Greater than (gt) and less than (lt) parameters in FastAPI Path() do not work in Swagger UI

huangapple go评论66阅读模式
英文:

Greater than (gt) and less than (lt) parameters in FastAPI Path() do not work in Swagger UI

问题

以下是您要翻译的内容:

使用的版本

  • python 3.9.9
  • FastAPI 0.95.1
  • uvicorn 0.22.0
  • firefox 102.8.0

在这个示例中,路径参数 item_id 设置为有效范围大于 100 (gt=100) 且小于 1000 (lt=1000)。
然而,在 Swagger UI 中无法识别它。
gele 正常工作。

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", gt=100, lt=1000)]
):
    return {"item_id": item_id}

使用 gtlt,约束既不显示在 UI 中,也不强制执行。

使用 gele,约束都在 UI 中显示并强制执行。

英文:

Versions used

  • python 3.9.9
  • FastAPI 0.95.1
  • uvicorn 0.22.0
  • firefox 102.8.0

In this example, the path parameter item_id is set up with a valid range > 100 (gt=100) and < 1000 (lt=1000).
However, it's not recognized in Swagger UI.
ge and le work fine.

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()

@app.get(&quot;/items/{item_id}&quot;)
async def read_items(
    item_id: Annotated[int, Path(title=&quot;The ID of the item to get&quot;, gt=100, lt=1000)]
):
    return {&quot;item_id&quot;: item_id}

with gt and lt, the constraints are neither shown in the UI nor enforced.
Greater than (gt) and less than (lt) parameters in FastAPI Path() do not work in Swagger UI

with ge and le, the constraints are both shown in the UI and enforced.
Greater than (gt) and less than (lt) parameters in FastAPI Path() do not work in Swagger UI

答案1

得分: 1

这似乎是与自动生成的 OpenAPI 架构有关的问题,该架构由 Swagger UI 用于提供交互式 API 文档。您可以直接查看架构:http://127.0.0.1:8000/openapi.json。根据您提供的示例,对于 item_id: int = Path(title="获取项目的ID", gt=100, lt=1000) 参数,您将看到:

{...,
  "schema": {
    "title": "获取项目的ID",
    "exclusiveMaximum": 1000,
    "exclusiveMinimum": 100,
    "type": "integer"
  },
  "name": "item_id",
  "in": "path"
}, ...

然而,根据Swagger 文档的描述,在使用 gtlt(意味着应该排除 maximumminimum 值的情况下),OpenAPI 架构应该如下所示:

{...,
  "schema": {
    "title": "获取项目的ID",
    "maximum": 1000,
    "exclusiveMaximum": true,
    "minimum": 100,
    "exclusiveMinimum": true,
    "type": "integer"
  },
  "name": "item_id",
  "in": "path"
}...

因此,exclusiveMaximumexclusiveMinimum 属性应该采用布尔值,而不是实际的数值。为了排除边界值,exclusiveMaximumexclusiveMinimum 都应设置为 true。这个问题之前已经在这里描述过,如果 FastAPI 迁移到 OpenAPI 3.1 时将得到解决(也请参阅Helen的回答)此主题)。在那之前,您可以查看以下解决方案。

可能的解决方案

解决方案 1

不要使用 gt/lt,您可以使用 ge/le。例如,如果 gt=100lt=1000,您可以改用 ge=101le=999。示例:

item_id: int = Path(title="获取项目的ID", ge=101, le=999)

解决方案 2

可以加载自己修改过的 OpenAPI 架构,如此处此处所示,但即使 Swagger UI 显示了 minimummaximum 值(如果使用了修改后的架构,类似于上面演示的架构),Swagger UI 仍然不会明确告诉用户应该排除 minimummaximum 值(例如,使用大于/小于符号)。此外,如果用户向 item_id 参数传递了,例如,1000 值,前端不会进行验证,Swagger UI 不会显示验证错误消息(例如,值必须小于1000),而如果使用 gele 参数,验证应该在后端进行,后端将以 422 Unprocessable Entity 错误回应,并在响应体中提供适当的验证错误消息。因此,生成的 OpenAPI 架构和 Swagger UI 都可能存在问题。

英文:

This seems to be an issue with the auto-generated OpenAPI schema, which is used by Swagger UI to provide the interactive API documentation. You could see the schema directly at: http://127.0.0.1:8000/openapi.json. Given the example you provided, for item_id: int = Path(title=&quot;The ID of the item to get&quot;, gt=100, lt=1000) parameter, you would see:

{...,
  &quot;schema&quot;: {
    &quot;title&quot;: &quot;The ID of the item to get&quot;,
    &quot;exclusiveMaximum&quot;: 1000,
    &quot;exclusiveMinimum&quot;: 100,
    &quot;type&quot;: &quot;integer&quot;
  },
  &quot;name&quot;: &quot;item_id&quot;,
  &quot;in&quot;: &quot;path&quot;
}, ...

However, as described in Swagger documentation, in the case of using gt and lt (meaning that the maximum and minimum values should be excluded from the range), the OpenAPI shcema should instead look like this:

{...,
  &quot;schema&quot;: {
    &quot;title&quot;: &quot;The ID of the item to get&quot;,
    &quot;maximum&quot;: 1000,
    &quot;exclusiveMaximum&quot;: true,
    &quot;minimum&quot;: 100,
    &quot;exclusiveMinimum&quot;: true,
    &quot;type&quot;: &quot;integer&quot;
  },
  &quot;name&quot;: &quot;item_id&quot;,
  &quot;in&quot;: &quot;path&quot;
}...

Hence, exclusiveMaximum and exclusiveMinimum attributes should take a boolean value, not the actual number value itself. In order to exclude both the boundary values, both exclusiveMaximum and exclusiveMinimum should be set to true. This issue has previously been described here and is meant to be resolved when/if FastAPI migrates to OpenAPI 3.1 (see Helen's answer around this topic as well). Until then, you may want to have a look at the following solutions.

Possible solutions

Solution 1

Instead of using gt/lt, you could use ge/le. If, for instance, gt=100 and lt=1000, you could instead use ge=101 and le=999. Example:

item_id: int = Path(title=&quot;The ID of the item to get&quot;, ge=101, le=999)

Solution 2

One could load their own modified OpenAPI shcema, as demonstrated here and here, but even though Swagger UI would display the minimum and maximum values (if a modified schema was used, similar to the one demonstrated above), Swagger UI would still not make it clear to the user that minimum and maximum values should be excluded (with greater/less than symbols, for instance). Also, if the user passed, for example, 1000 value to the item_id parameter, the validation would not take place in the frontend and Swagger UI would not display a validation error message (e.g., Value must be less than 1000)&mdash;which would happen if ge and le parameters wre used instead&mdash;but validation should rather take place in the backend, which would respond with a 422 Unprocessable Entity error and an appropriate validation error message in the response body. Hence, there might be issues with both the generated OpenAPI shcema and Swagger UI as well.

huangapple
  • 本文由 发表于 2023年5月18日 07:43:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76276863.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定