Is it expected that FastAPI cannot handle URL-encoded GET parameters? I searched the docs and via google but couldn't find any hints why this is or how to change the behaviour.
See the example below. I'm trying to pass float numbers as GET parameters with the . being URL-encoded. I'm getting the response that the number isn't a valid float.
from pydantic import BaseModel
from fastapi import FastAPI
app = FastAPI()
class LongitudinalDiameterAndQuantity(BaseModel):
diameter: float
quantity_a: float
quantity_b: float
@app.get("/column/longitudinal/diameter_quantity", response_model=LongitudinalDiameterAndQuantity)
def read_root(As: float, a: float, b: float):
# TODO: Feed parameters into ML model and get results
return LongitudinalDiameterAndQuantity(diameter=As, quantity_a=a, quantity_b=b)
URL: http://localhost:8000/column/longitudinal/diameter_quantity?As=1.2&a=1.2&b=1.2
As expected: Response code 200, content: {"diameter":1.2,"quantity_a":1.2,"quantity_b":1.2}
URL: http://localhost:8000/column/longitudinal/diameter_quantity?As=1%2C2&a=1%2C2&b=1%2C2
Not expected: Response code 422, content:
{
"detail":[
{
"loc":[
"query",
"As"
],
"msg":"value is not a valid float",
"type":"type_error.float"
},
{
"loc":[
"query",
"a"
],
"msg":"value is not a valid float",
"type":"type_error.float"
},
{
"loc":[
"query",
"b"
],
"msg":"value is not a valid float",
"type":"type_error.float"
}
]
}
If there is not a special reason, declare and return your models like this
from pydantic import BaseModel
from fastapi import FastAPI
app = FastAPI()
class LongitudinalDiameterAndQuantity(BaseModel):
diameter: float
quantity_a: float
quantity_b: float
@app.get("/column/longitudinal/diameter_quantity", response_model=LongitudinalDiameterAndQuantity)
def read_root(model: LongitudinalDiameterAndQuantity):
return model
Thanks ycd. The reason is, that the code is not complete. Actually later the input parameters will not be directly used as output parameters. What I could have done is have a separate model for the input data maybe.
@MarcelKr you can still use the parameters with model.diameter etc.
Just tried the modifications you propose. The problem is, that FastAPI is interpreting def read_root(model: LongitudinalDiameterAndQuantity): as needing a request body. However a request body for GET isn't allowed.
So to circumvent the problem I might switch to a POST with JSON body for now. However this is not a clean solution I think :/
@MarcelKr try this
from fastapi import Depends
def read_root(model: LongitudinalDiameterAndQuantity = Depends())
Thanks again @ycd, but I feel that we're avoiding the actual problem or question I'm having.
However I think I found the answer: It seems that the Library I'm using - or rather the C# code generated from swagger - is using , instead of . as decimal separator when generating the GET parameters. URL-encoding , results in %2C (I initially thought that %2C is .). Obviously FastAPI or Python is expecting floats with a . instead of a ,. So that's why it generates the error message value is not a valid float.
To test this I created an endpoint like this:
@app.get("/test")
def read_test(test: str):
return test
Using the built-in /docs/ to test it. Putting in . is never encoded, but , for instance is encoded as %2C (or ? -> %3F) and it's correctly returned. So it seems that FastAPI is handling the encoding correctly and the root cause was simply using , instead of . for decimal separation by my swagger-generated client API.
So I'll double check the swagger-codegen why they generate , instead of . which is quite qeird I think.
Ooooooooooooh. I missunderstood the whole question, :disappointed: i think If you use %2E it 'd be fine.
Also you can check a character's hexadecimal equivalent with
echo -n . | xxd -p
2e
Ooooooooooooh. I missunderstood the whole question
Haha, no problem 馃槃
Thanks for the hint regarding xxd 馃憤
The problem (using , instead of . in the query string) seems to be originating from the RestSharp library which is used by the C# code generated from Swagger. When generating the URLs the current locale is taken into account. On my system (german locale), the decimal separator is a ,. When I set the locale to invariant it's using . as expected. Who would have thought that? 馃う
Thanks for the help here @ycd ! :clap: :bow:
Thanks for reporting back and closing the issue @MarcelKr :+1:
Most helpful comment
Haha, no problem 馃槃
Thanks for the hint regarding xxd 馃憤