Flask + Connexion + Swagger 启动失败

问题描述 投票:0回答:1

问题

我启动了一个 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)

结果

  • Python 3.12.0
  • 连接3.0.2
  • 烧瓶3.0.0
  • swagger_ui_bundle 1.1.0
  • Werkzeug 3.0.1

文件

目录结构

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.
python flask swagger werkzeug connexion
1个回答
0
投票

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 设置的更改等。

© www.soinside.com 2019 - 2024. All rights reserved.