Skip to content

Search all registered APIs when matching a request path #2108

@damienklotz77

Description

@damienklotz77

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions