2

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("/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}

with gt and lt, the constraints are neither shown in the UI nor enforced. enter image description here

with ge and le, the constraints are both shown in the UI and enforced. enter image description here

Chris
  • 18,724
  • 6
  • 46
  • 80
jung rhew
  • 800
  • 6
  • 9
  • Possible duplicate of [FastAPI's auto generated OpenAPI file not valid according to Insomnia](https://stackoverflow.com/q/75862523/113116) – Helen May 18 '23 at 08:22
  • 1
    I'd like to bring attention to that the incorrect `exclusiveMinimum` and `exclusiveMaximum` specification in `openapi.json`, pointed out by Chris above, is already filed at https://github.com/tiangolo/fastapi/discussions/9140. – jung rhew May 18 '23 at 07:17

1 Answers1

1

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="The ID of the item to get", gt=100, lt=1000) parameter, you would see:

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

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:

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

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="The ID of the item to get", 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)—which would happen if ge and le parameters wre used instead—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.

Chris
  • 18,724
  • 6
  • 46
  • 80
  • Thanks a lot for the explanation. However, it seems to be a tricky issue to address. – jung rhew May 18 '23 at 06:42
  • Thanks again. I was looking for where to file a ticket. I was about to do it in swagger-ui github but it said "we can't accept bugs in the Swagger/OpenAPI specifications." I'll do that in the link you recommended. – jung rhew May 18 '23 at 07:05
  • 1
    I'd like to bring attention to that the incorrect `exclusiveMinimum` and `exclusiveMaximum` specification in `openapi.json`, pointed out by Chris above, is already filed at https://github.com/tiangolo/fastapi/discussions/9140. – jung rhew May 18 '23 at 16:48