3

I am creating an application with FastAPI and so far it goes like this:

enter image description here

But I'm having a problem with the endpoints. The /api/items/filter route has two query parameters: name and category. However, it gives me the impression that it is being taken as if it were api/items/{user_id}/filter, since when I do the validation in the documentation it throws me an error saying that I have not passed a value for user_id. (Also, previously it asked me to be authenticated (the only route that needed authentication was api/items/{user_id}. The problems are fixed when I define this endpoint first as shown below:

enter image description here

Why is this happening? Is there a concept that I am not clear?

Chris
  • 18,724
  • 6
  • 46
  • 80
Diegol
  • 87
  • 7
  • Does this answer your question? [How to define multiple API endpoints in FastAPI with different paths but the same path parameter?](https://stackoverflow.com/questions/74498191/how-to-define-multiple-api-endpoints-in-fastapi-with-different-paths-but-the-sam) – Chris Dec 28 '22 at 06:04
  • Related answer can also be found [here](https://stackoverflow.com/a/73113792/17865804). On a side note, if you would like to customise the order for the API methods in Swagger UI, please take a look at [this answer](https://stackoverflow.com/a/73210294/17865804). – Chris Dec 28 '22 at 06:06

1 Answers1

2

Ordering your endpoints matters! Endpoints are matched in order they are declared in your FastAPI object. Let say you have only two endpoints, in this order:

  1. api/items/{user_id}
  2. api/items/filter

In this order, when you request endpoint api/items/user_a, your request will be routed to (1) api/items/{user_id}. However, if you request api/items/filter, this also will be routed to (1) api/items/{user_id}! That is because filter is a match for {user_id}, and since this endpoint is evaluated before the second endpoint is evaluated for a match, the second endpoint is not evaluated at all.

That is also why you are asked for authorization; you think you are requesting endpoint 2, but your request is actually routed to endpoint 1, with path parameter {user_id} = "filter".

So, ordering your endpoints is important, and it is just where in your application you are defining them. See here in the docs.

JarroVGIT
  • 4,291
  • 1
  • 17
  • 29
  • Thank you very much for your answer! Could you help me with something else? Currently I have the endpoints as in the second image: api/items/filter -- api/items/{user_id} -- api/items/{name} --. As you can imagine now I have the problem with api/items/{user_id} and api/items/{name} since when I access api/items/{name} actually api/items/{user_id} is being evaluated. Both endpoints have path parameters so there is no point in ordering them. What should I do in those cases? should i change the last endpoint to something like api/items/byname/{name}? Thank you! – Diegol Dec 29 '22 at 03:37
  • 1
    You have two options: you could use different types if you can, like so: {user_id:int} and {name:str} and make sure the user_id is in front of the name endpoint (in order) because “123” can be evaluated to string but “onetwothree” not to an int. This only works if your user_id is an int though, if both are strings then you must indeed change one of the endpoints to be more unique. – JarroVGIT Dec 29 '22 at 10:01
  • 1
    Thanks a lot! I have opted for the solution of using different types and it has worked for me! – Diegol Dec 29 '22 at 22:26