Search code examples
pythonflaskhttp-status-code-404fastapi

Mounting Flask app in FastAPI raises a 404 Not Found error response


I mounting a flask app on FastAPI with WSGIMiddleware and I want root "/" to be my flask app and "/api" to be a FastAPI route. Here is my code

from fastapi import FastAPI, Request
from fastapi.middleware.wsgi import WSGIMiddleware
from flask import Flask

fastapi = FastAPI()

app = Flask(__name__)

fastapi.mount("/", WSGIMiddleware(app=app))

i run it with uvicorn :

from app import fastapi
import uvicorn

if __name__ == '__main__':
    uvicorn.run(fastapi)

this is my route for test for api and flask app :

@fastapi.get("/api")
def test():
    return {"hello": "world"}

@app.get("/")
@app.route('/')
def index():
    return "Hello world"

Flask part is working perfectly fine, but when I go to http://127.0.0.1:8000/api I get a 404 Not Found error response. How can I fix this problem?


Solution

  • In your case, you need to make sure to mount the Flask app at the end of the code, as demonstrated in the example given in the documentation. The reason is simply because the order in which the endpoints are defined matters, as endpoints are evaluated in order (see this answer and this answer for more details and examples).

    What is "Mounting"

    "Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.

    This is different from using an APIRouter as a mounted application is completely independent. The OpenAPI and docs from your main application won't include anything from the mounted application, etc.

    Thus, since you are mounting the Flask app under the path /, every request under that path will be handled by the Flask application, while the rest will be handled by FastAPI. Hence, the 404 Not Found error response when trying to hit the /api endpoint. This response actually comes from the Flask app, since it does not include a /api endpoint. So, you need to define the /api endpoint from FastAPI app before mounting the Flask app, as shown in the example given below. If you mounted the Flask app under a different path, such as /v1, that would not interfere with any of FastAPI's endpoints, you could still mount the Flask app in the way you currently do.

    Working Example

    from fastapi import FastAPI
    from fastapi.middleware.wsgi import WSGIMiddleware
    from flask import Flask, escape, request
    
    flask_app = Flask(__name__)
    
    
    @flask_app.route("/")
    def flask_main():
        name = request.args.get("name", "World")
        return f"Hello, {escape(name)} from Flask!"
    
    
    app = FastAPI()
    
    
    @app.get("/api")
    def read_main():
        return {"message": "Hello World"}
    
    
    app.mount("/", WSGIMiddleware(flask_app))