diff --git a/src/simdb/remote/apis/__init__.py b/src/simdb/remote/apis/__init__.py index b75a9680..2f8a7803 100644 --- a/src/simdb/remote/apis/__init__.py +++ b/src/simdb/remote/apis/__init__.py @@ -36,6 +36,26 @@ def register(api, version, namespaces): version_str = version.replace(".", "_") blueprint = Blueprint(f"api_{version_str}", f"{__name__}.{version_str}") blueprints[version] = blueprint + + def index(): + return jsonify( + { + "api": "simdb", + "api_version": api.version, + "server_version": __version__, + "endpoints": [ + request.url + "simulations", + request.url + "files", + request.url + "validation_schema", + request.url + "metadata", + request.url + "upload_options", + ], + "documentation": request.url + "docs", + } + ) + + api.render_root = index + api.init_app(blueprint) for namespace in namespaces: @@ -78,21 +98,7 @@ def handle_authentication_error(err: Exception): class Index(Resource): @api.doc(security=[]) def get(self): - return jsonify( - { - "api": "simdb", - "api_version": api.version, - "server_version": __version__, - "endpoints": [ - request.url + "simulations", - request.url + "files", - request.url + "validation_schema", - request.url + "metadata", - request.url + "upload_options", - ], - "documentation": request.url + "docs", - } - ) + return index() @api.route("/token") class Token(Resource): diff --git a/tests/remote/api/test_index.py b/tests/remote/api/test_index.py new file mode 100644 index 00000000..608fadcc --- /dev/null +++ b/tests/remote/api/test_index.py @@ -0,0 +1,16 @@ +import pytest + +from simdb.remote.apis import blueprints + + +@pytest.mark.parametrize("version", list(blueprints)) +def test_versioned_index(client, version): + """The versioned root must serve the index JSON, not flask-restx's 404 root.""" + rv = client.get(f"/{version}/") + + assert rv.status_code == 200 + assert rv.json["api"] == "simdb" + # v1 reports "1.0" for blueprint key "v1", so only compare the prefix + assert rv.json["api_version"].startswith(version.lstrip("v")) + assert "server_version" in rv.json + assert any(url.endswith("simulations") for url in rv.json["endpoints"])