-
-
Notifications
You must be signed in to change notification settings - Fork 780
Description
Description
Adding an OpenAPI whose base path is a subset of the base path of an already registered OpenAPI
will result in a 404 error on all the endpoints of the already registered OpenAPI.
Observation : No issues occur when first adding the OpenAPI whose base path is a subset of the other OpenAPI’s base path.
Pre-analysis
Based on code analysis, Connexion seems to create a new API object and add it to a list of registered API objects without utilizing the base URL.
The issue seems to come from the feature where Connexion attempts to match the HTTP request path against a base path within the list of registered APIs.
The list of API objects is ordered.
It seems that when Connexion receives the request path http://127.0.0.1:8000/path1 (cf steps to reproduce), the matcher finds a perfect match with the base URL http://127.0.0.1:8000 of the first API object, and Connexion then locks onto this specific object.
It subsequently searches for the registered path /path1 within this first API object, fails to find it, and gives up.
If the APIs are registered in the reverse order, the search will successfully find a match.
Actual behaviour
This implies that the current implementation requires the base URLs of all registered APIs to be unique and not share a common prefix.
Expected behaviour
Perhaps the search logic could be extended to check all registered APIs instead of stopping at the first failure ?
Steps to reproduce
Create the 3 following files :
openapi1.yaml
openapi: 3.0.4
info:
title: My title
version: '1.0'
servers:
- url: http://127.0.0.1:8000/path1
paths:
/endpoint1:
get:
operationId: script.myfunction1
responses:
'200':
description: My description
openapi2.yaml
openapi: 3.0.4
info:
title: My title
version: '1.0'
servers:
- url: http://127.0.0.1:8000
paths:
/endpoint2:
get:
operationId: script.myfunction2
responses:
'200':
description: My description
main.py
from connexion import AsyncApp
def myfunction1():
return "OK1"
def myfunction2():
return "OK2"
if __name__ == "__main__":
app = AsyncApp(__name__)
app.add_api(specification="openapi1.yaml", strict_validation=True)
app.add_api(specification="openapi2.yaml", strict_validation=True)
app.run()curl http://127.0.0.1:8000/path1/endpoint1
{"type": "about:blank", "title": "Not Found", "detail": "Not Found", "status": 404}
curl http://127.0.0.1:8000/endpoint2
"OK2"By adding /path2 to the second openapi, it works.
By inversing the order of adding the two openapis to AsyncApp, it works too.