Reputation: 473
I have created a openapi.yml file and initiated a connexion app and started the app without any errors.
My directory structure is as follows:
/my_app
/app
__init__.py
/api
__init__.py
api.py # My API endpoint implementations
/models
__init__.py
models.py # My SQLAlchemy models
swagger.yml # OpenAPI specification
.env
config.py # Configuration settings
main.py # Entry point for the application
I am using the following dependencies:
connexion[swagger-ui, uvicorn, flask]==3.0.5
annotated-types==0.6.0
anyio==3.7.1
autopep8==2.0.4
blinker==1.7.0
click==8.1.7
connexion[swagger-ui, uvicorn, flask]==3.0.5
Flask==3.0.1
flask-sqlacodegen==2.0.0
Flask-SQLAlchemy==3.1.1
gunicorn==21.2.0
h11==0.14.0
idna==3.6
inflect==7.0.0
itsdangerous==2.1.2
Jinja2==3.1.3
MarkupSafe==2.1.4
mysqlclient==2.2.1
packaging==23.2
pycodestyle==2.11.1
pydantic_core==2.16.1
pydantic==2.6.0
PyMySQL==1.1.0
python-dotenv==1.0.1
sniffio==1.3.0
SQLAlchemy==2.0.25
SQLAlchemy-serializer==1.4.1
starlette==0.32.0.post1
typing_extensions==4.9.0
uvicorn==0.27.1
Werkzeug==3.0.1
Inside the app/_init_.py I have defined the following function:
def create_app(config_class=Config, **kwargs):
load_dotenv()
# Create the Connexion application
connex_app = connexion.FlaskApp(__name__, specification_dir='./')
connex_app.add_api("swagger.yml") #, base_path='/api/v1', arguments={'title': 'API v1'}, strict_validation=False, validate_responses=False, pythonic_params=True, name='api_v1_admin')
application = connex_app.app
# Load configuration from .env file
application.config.from_object(config_class)
application.config.update(kwargs)
# initialize db connection
from app.models import init_app
init_app(application)
return connex_app
From the main.py I am calling the following:
if __name__ == "__main__":
app = create_app()
app.run(host="0.0.0.0", port=8080)
The app starts without any error and the logs suggest that the app loaded the openapi file correctly.
INFO: Started server process [17447]
INFO: Waiting for application startup.
DEBUG:connexion.middleware.abstract:Adding /api/v1/agent...
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.middleware.abstract:Adding /api/v1/agent/{agentId}...
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json', 'application/xml']
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json', 'application/xml']
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.middleware.validation:Strict Request Validation: None
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json', 'application/xml']
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.middleware.security:... Security: [{'admin_auth': ['write:agent', 'read:agent']}]
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit)
I have verified that my openapi yml file is syntactically correct.
The issue occurs when I try to call an api like so: http://localhost:8080/api/v1/agent/1
Connexion middleware tries to register the openapi endpoints again. Its evident from the logs below:
DEBUG:connexion.middleware.abstract:Adding /api/v1/agent...
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.operations.openapi3:consumes: ['application/json']
DEBUG:connexion.operations.openapi3:produces: ['application/json']
DEBUG:connexion.middleware.abstract:Adding /api/v1/agent/{agentId}...
DEBUG:connexion.operations.openapi3:consumes: []
DEBUG:connexion.operations.openapi3:produces: ['application/json']
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "xxx/venv/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "xxx/venv/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "xxx/venv/lib/python3.11/site-packages/connexion/middleware/main.py", line 497, in __call__
self.app, self.middleware_stack = self._build_middleware_stack()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "xxx/venv/lib/python3.11/site-packages/connexion/middleware/main.py", line 338, in _build_middleware_stack
app.add_api(
File "xxx/venv/lib/python3.11/site-packages/connexion/apps/flask.py", line 141, in add_api
self.app.register_blueprint(api.blueprint)
File "xxx/venv/lib/python3.11/site-packages/flask/sansio/scaffold.py", line 45, in wrapper_func
return f(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "xxx/venv/lib/python3.11/site-packages/flask/sansio/app.py", line 599, in register_blueprint
blueprint.register(self, options)
File "xxx/venv/lib/python3.11/site-packages/flask/sansio/blueprints.py", line 310, in register
raise ValueError(
ValueError: The name '/api/v1' is already registered for a different blueprint. Use 'name=' to provide a unique name.
INFO: 127.0.0.1:51609 - "GET /api/v1/agent/1 HTTP/1.1" 500 Internal Server Error
Can anyone suggest why this is happening? Why connexion tries adding openapi's endpoints again?
Note: If I manually set routes, the project is working fine.
Upvotes: 1
Views: 337