我启动了一个 Flask 应用程序(+ Connexion 和 Swagger UI)并尝试打开 http://127.0.0.1:5000/api/ui。浏览器显示
starlette.exceptions.HTTPException: 404: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
% pip install "connexion[flask, swagger-ui]"
% export FLASK_APP="app"
(Prepare files)
% flask run --debug
(Access http://127.0.0.1:5000/api/ui)
结果
目录结构
app/
__init__.py
openapi.yaml
hello.py
__init__.py
from connexion import FlaskApp
from flask.app import Flask
from pathlib import Path
BASE_DIR = Path(__file__).parent.resolve()
def create_app() -> Flask:
flask_app: FlaskApp = FlaskApp(__name__)
app: Flask = flask_app.app
flask_app.add_api("openapi.yaml")
return app
openapi.yaml
openapi: 3.0.3
info:
title: "test"
description: "test"
version: "1.0.0"
servers:
- url: "/api"
paths:
/hello:
get:
summary: "hello"
description: "hello"
operationId: "hello.say_hello"
responses:
200:
description: "OK"
content:
text/plain:
schema:
type: string
example: "hello"
hello.py
def say_hello() -> str:
return 'Hello, world!'
基于这些设置,我相信我可以在http://127.0.0.1:5000/api/ui看到Swagger UI。但是,我遇到了以下错误消息。
Traceback (most recent call last):
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/flask/app.py", line 867, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/flask/app.py", line 841, in dispatch_request
self.raise_routing_exception(req)
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/flask/app.py", line 450, in raise_routing_exception
raise request.routing_exception # type: ignore
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/flask/ctx.py", line 353, in match_request
result = self.url_adapter.match(return_rule=True) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/werkzeug/routing/map.py", line 624, in match
raise NotFound() from None
werkzeug.exceptions.NotFound: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/flask/app.py", line 1478, in __call__
return self.wsgi_app(environ, start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/flask/app.py", line 1458, in wsgi_app
response = self.handle_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/flask/app.py", line 1455, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/flask/app.py", line 869, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/flask/app.py", line 759, in handle_user_exception
return self.ensure_sync(handler)(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/myusername/tmp/.venv/lib/python3.12/site-packages/connexion/apps/flask.py", line 245, in _http_exception
raise starlette.exceptions.HTTPException(exc.code, detail=exc.description)
starlette.exceptions.HTTPException: 404: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
TL:DR:您需要一个 ASGI 服务器来运行您的应用程序。
connexion github 问题跟踪器上有类似问题。
这只会引导您找到有关运行应用程序的文档,可以在此处找到该文档。
考虑到上述内容,我设法创建了自己的解决方案:
__init__.py
:
from connexion import FlaskApp
def create_app():
app = FlaskApp(__name__)
app.add_api("openapi.yaml", validate_responses=True)
return app
app = create_app()
openapi.yaml
:
openapi: 3.0.3
info:
title: test
description: test
version: 1.0.0
paths:
/hello:
get:
summary: hello
description: hello
operationId: app.hello.say_hello
responses:
200:
description: OK
content:
text/plain:
schema:
type: string
example: hello
如需更多帮助,请参阅下面我使用的 docker 设置:
docker-compose.yaml
:
version: '3.8'
services:
test-api:
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
env_file:
- .env
ports:
- '8000:8000'
volumes:
- ./app:/usr/src/app/app
Dockerfile
:
FROM public.ecr.aws/lambda/python:3.10
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN pip3 install --no-cache-dir -r requirements.txt
ENV FLASK_RUN_HOST=0.0.0.0
ENV FLASK_RUN_PORT=8000
EXPOSE 8000
COPY entrypoint.sh /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
entrypoint.sh
:
#!/bin/sh
gunicorn -w 1 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000 app:app --reload
# Keep the script running to keep the container alive
tail -f /dev/null
requirements.txt
:
connexion[flask, swagger-ui, uvicorn]==3.0.2
gunicorn==21.2.0
Werkzeug==3.0.1
Flask==3.0.0
setuptools >= 21.0.0
swagger-ui-bundle==1.1.0
项目结构:
project-root/
|-- app/
| |-- __init__.py
| |-- hello.py
| |-- openapi.yaml
|-- Dockerfile
|-- docker-compose.yml
|-- entrypoint.sh
|-- requirements.txt
|-- .env
希望这有帮助!我建议从这个工作点开始尝试特定的设置,例如 CORS、数据库设置、迁移、docker 设置的更改等。