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

huangapple go评论72阅读模式
英文:

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 the test for the 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?

英文:

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?

答案1

得分: 1

在你的情况下,你需要确保在代码的最后使用mount来挂载Flask应用程序,就像文档中示例所示。原因很简单,端点定义的顺序很重要,因为端点按照顺序进行评估(参见这个答案这个答案以获取更多详细信息和示例)。

什么是"挂载"("Mounting")

"挂载"意味着在特定路径下添加一个完整的"独立"应用程序,然后负责处理所有子路径

这与使用APIRouter不同,因为挂载的应用程序是完全独立的。来自主应用程序的OpenAPI和文档不会包含来自挂载的应用程序的任何内容,等等。

因此,由于你将Flask应用程序挂载在路径/下,因此该路径下的每个请求都将由Flask应用程序处理,而其他请求将由FastAPI处理。因此,在尝试访问/api端点时出现404 Not Found错误响应。实际上,这个响应来自Flask应用程序,因为它不包括/api端点。因此,你需要在挂载Flask应用程序之前从FastAPI应用程序中定义/api端点,就像下面的示例所示。如果你将Flask应用程序挂载在不同的路径下,比如/v1,那将不会干扰FastAPI的任何端点,你仍然可以按照你目前的方式挂载Flask应用程序。

工作示例

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))
英文:

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))

huangapple
  • 本文由 发表于 2023年4月20日 01:12:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76057185.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定