1

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?

1 Answer 1

0

Looks like data can be used at the same time as files:

with TestClient(app) as client:
  client.post(
    "/test",
    data={"upload.json": "STRING CONTENT"},
    files={
      "file2": ("file2.pdf", "FILE CONTENT", "application/octet-stream")
    }
)

This sends the parts as both str and FileUpload.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.