Fastapi: Check python-multipart when using Form and raise early

Created on 19 Jun 2020  路  3Comments  路  Source: tiangolo/fastapi

First check

  • [x] I added a very descriptive title to this issue.
  • [x] I used the GitHub search to find a similar issue and didn't find it.
  • [x] I searched the FastAPI documentation, with the integrated search.
  • [x] I already searched in Google "How to X in FastAPI" and didn't find any information.
  • [x] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [x] I already checked if it is not related to FastAPI but to Pydantic.
  • [x] I already checked if it is not related to FastAPI but to Swagger UI.
  • [x] I already checked if it is not related to FastAPI but to ReDoc.
  • [x] After submitting this, I commit to:

    • Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.

    • Or, I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.

    • Implement a Pull Request for a confirmed bug.

Example

Here's a self-contained minimal, reproducible, example with my use case:

from fastapi import FastAPI, Form

app = FastAPI()


@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
    return {"username": username}

Description

  • Create a new venv
  • Install only FastAPI and Uvicorn
  • Run that example
  • Try it in the docs
  • It returns a 400 response with:
{
  "detail": "There was an error parsing the body"
}

The problem is that it's trying to read form data (multipart), and for that it requires the package python-multipart installed.

It is documented in the docs in FastAPI and Starlette, but forgetting to install it and running the app ends up in that behavior that is not explicit nor obvious. Everything works normally, except that specific path operation, that only breaks after a receiving a request (which is worse).

To make things more complex, the package required is python-multipart. But there's another Python package called just multipart.

And both packages are imported as:

import multipart

This can lead to a problem that is really difficult to debug: an environment with both packages installed, in some runs could import the correct package and everything would work, but in other runs, it could import the other package, which would cause problems. That would make it one of those scary ghost bugs that disappear and appear. :bug: :ghost:

And even worse, the problems will only show up after receiving a request in a path operation that requires reading form data, not at start up.

The solution you would like

In FastAPI, the main ways to get form data are quite explicit, using Form, UploadFile, bytes.

That means that it's possible to detect that a path operation will try to read form data on initialization.

I would like FastAPI to raise an error and crash fast when there's a path operation that uses something that requires to read form data, right on initialization (while creating the instances).

In Starlette (or in FastAPI when using the request directly), there's no way to know if the code will try to access form data from the request.

But in FastAPI, as it is declared in function parameters that are read during initialization, it would be possible to error out early.

It should log an error saying that form data requires python-multipart and then raise the exception. This would be triggered right while starting an application.

But it would only raise an exception if there's a path operation that actually requires form data, otherwise, everything would work as normal.

It should ideally also detect if the imported multipart is the correct one or not. If the incorrect one is installed/imported, it should log an error informing that clearly, explaining that multipart is not compatible with python-multipart, that the user has to uninstall multipart and then install python-multipart.

There's a point in code that decides if a path operation should read from JSON or from Form data while creating the request body field for a path operation. Whatever does the check about python-multipart, would ideally run from that same point.

Describe alternatives you've considered

Leave it as is. But it's frustrating when it happens.

It took me a while (days) to debug that there could be 2 multipart packages conflicting. If it was so difficult for me (that I'm supposed to know enough about FastAPI, I guess :shrug: ), I imagine how frustrating that could be for someone new.

Environment

  • OS: [e.g. Linux / Windows / macOS]: All
  • FastAPI Version [e.g. 0.3.0]: All

To know the FastAPI version use:

python -c "import fastapi; print(fastapi.__version__)"
  • Python version: All

To know the Python version use:

python --version

Additional context

Tom created an issue in the repo suggesting a name change: https://github.com/andrew-d/python-multipart/issues/16

But that will probably take some time to happen (if it happens).

confirmed enhancement good first issue

Most helpful comment

@YKo20010 and I will be working on this issue!

All 3 comments

@YKo20010 and I will be working on this issue!

I saw a lot of questions on StackOverflow related to this issue. Good one! :)

This is available in FastAPI version 0.60.2 :rocket: :tada:

Thanks for the work on this @chrisngyn, @YKo20010, @kx-chen ! :coffee: :cake:

Was this page helpful?
0 / 5 - 0 ratings