I'm working against an API specification outside my control. It expects to POST multipart/form-data to my server. Some parts are sent as files, some are sent as text.
I want to write a test using TestClient that sends both a file and text parts.
I don't have access to the exact body that is posted, so I don't know exactly how the multipart form data looks. But I can parse the input from the external system with FastAPI's Request. Some parts are of type UploadFile and some parts are of type str.
The Starlette source for FormData is a ImmutableMultiDict[str, Union[UploadFile, str]]. So this looks like a valid use case.
The following code can handle the POST:
@router.post("/test")
async def test_multipart(
request: Request,
):
content_type = request.headers.get("content-type")
if content_type.startswith("multipart/form-data"):
async with request.form() as form:
for (filename, form_file) in form.items():
logger.info("Form file type: %s", str(type(form_file)))
# This is the line I want to test:
if type(form_file) is str:
print("Got data as string")
elif type(form_file) is UploadFile:
print("Got data as UploadFile")
if form_file.content_type == "application/octet-stream":
print("Got octet")
I can test the UploadFile parts easily:
with TestClient(app) as client:
client.post(
"/test",
files={
"file1": ("upload.json", "STRING CONTENT"),
"file2": ("file2.pdf", "FILE CONTENT", "application/octet-stream")
}
)
But I want that first entry to appear as str not UploadFile. How can I do this?