I'm building a plain HTML, JavaScript, and CSS chat widget for a Shopify site. Users should be able to send a text message, a file without text, or both. The widget will call a FastAPI endpoint that accepts files with UploadFile.
I'm considering three approaches:
1. Put the message and file fields into one multipart/form-data request every time.
2. Use multipart/form-data when a file is attached, but switch to application/json for text-only messages.
3. Send the message and file as separate requests and coordinate them on the backend.
Which approach would you recommend, and are there any implementation details I should watch out for?
2 Answers
FastAPI can handle an optional file cleanly with a form field and an optional UploadFile, for example: `message: str = Form("")` and `file: UploadFile | None = File(None)`. Once a route uses File() or Form(), treat it as a multipart endpoint rather than trying to make the same route switch between JSON and form parsing. The JSON-versus-multipart approach usually means maintaining separate request paths for little practical benefit.
I’d use one multipart/form-data request for every chat event. Sending multipart without an actual file has very little overhead, and it keeps the frontend and backend logic consistent. Splitting the message and upload into separate requests can create synchronization and partial-failure problems—for example, the text might arrive before the file, or the upload could fail after the message is already displayed.

That makes sense. Keeping one request type should also make it easier to keep the chat message and attachment associated with each other.