I am using FastAPI to serve some ML models and I have a Streamlit
basic UI using Python Requests
module.
One of my service is getting an image through a POST request and it is working like a charm.
Server side
@app.post("/segformer")
async def segformer(file: Optional[UploadFile] = None):
curl given by {BASE_URI}/docs
curl -X 'POST' \
'http://localhost:8080/segformer' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg'
Client side using Python Requests
response = requests.post(f"{BASE_URI}/segformer", files=files)
As soon as I want to add additional parameters, it gets creepy. For example:
Server side
@dataclass
class ModelInterface:
model_name: str = "detr"
tags: List[str] = Query(...)
@app.post("/detr")
async def detr(file: UploadFile = File(...), model: ModelInterface = Depends()):
curl -- given by {BASE_URI}/docs
curl -X 'POST' \
'http://localhost:8080/detr?model_name=detr&tags=balloon&tags=dog' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg'
Until that point everything works fine. Once I want to convert that call using Python Requests
, I have some issues, which always end up in /detr HTTP/1.1" 400 Bad Request
error.
Here is what I've tried:
Client side using Python Requests
headers = {
"Content-type": "multipart/form-data",
"accept": "application/json"
}
payload = {
"tags": ["balloon", "dog"]
}
response = requests.post(
f"{BASE_URI}/detr",
headers=headers,
json=payload, <- also *data*
files=files,
)
At the end it seems that the problem narrows on how to convert this:
curl -X 'POST' \
'http://localhost:8080/detr?tags=balloon&tags=dog' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg'
to a valid Python Requests
call!
I also faced the issue that the following FastAPI code:
@dataclass
class ModelInterface:
model_name: str = "detr"
tags: List[str] = None
@app.post("/detr2")
async def detr2(file: UploadFile = File(...), model: ModelInterface = Form(...)):
...
translates to this curl
command:
curl -X 'POST' \
'http://localhost:8080/detr2' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@image1.jpg;type=image/jpeg' \
-F 'model={
"model_name": "detr",
"tags": [
"balloon", "dog"
]
}'
which fails with a "POST /detr2 HTTP/1.1" 422 Unprocessable Entity
error