Repository navigation
Conversation
The document was copied from NodeNorm Redis and never pruned, so it advertised TRAPI 1.5 (info.x-trapi), carried 145 schemas no path referenced, named RENCI's developer as the contact and sent readers to /get_curie_prefixes, which this service has never served. It also failed openapi-spec-validator: the /get_allowed_conflations response had no description, and FilterKgraphTopNParameters.max_edges declared maximum 0 (NCATSTranslator/NodeNormalization#409). Rewritten from scratch against build_handlers(): the six routes this service registers, nothing else. Responses that were `schema: {}` now have schemas (NormalizedNodes, SetIDResponse), the FastAPI 422 responses are replaced by the 400 the Tornado handlers raise, and the examples are taken from the live CI instance. The servers block lists the ci and test deployments at ITRB instead of RENCI. Contact is Will Liu and the team is DOGSURF (biothings#35); infores and termsOfService are unchanged for now. info.version is bumped to 1.1.0 because /status reports it and the response shapes change in the next commit. handlers/curie_prefix.py was an unregistered copy of the semantic-types handler (its class is even named SemanticTypeHandler), so it goes too. Refs biothings#35, biothings#36 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
GET /get_allowed_conflations finished a bare list, and Tornado's write()
refuses a top-level list ("Lists not accepted for security reasons"),
so it returned HTTP 500 on every deployment. It now returns
{"conflations": [...]}, which is also what NodeNorm Redis returns.
GET /get_semantic_types lower-cased every class ("biolink:namedthing");
NodeNorm Redis returns the Biolink class URI as is ("biolink:NamedThing").
/openapi.json now redirects to /webapp/openapi.json so the FastAPI
default address used by NodeNorm Redis, SmartAPI and Babel Validation
works here too; it is excluded from OpenTelemetry like the other static
paths.
The POST set-ID test posted a single object where the handler expects
a list of sets, and the normalized-nodes docstring showed a "curie" key
where the handler reads "curies"; both corrected. POST /get_setid still
answers with an object keyed "0", "1", ... (the same Tornado limitation);
returning a list as NodeNorm Redis does is a breaking change, so it is
left to its own pull request.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The document is hand-written and served as a static file, so these tests are what stops it drifting: the spec validates; its paths are exactly the routes build_handlers() registers; each path documents the GET/POST methods its handler defines; each GET documents the query parameters its handler reads (found by scanning the handler source for get_argument calls); and the SetIDResponse schema lists the dataclass's fields. Each was checked to fail when the spec is mutated. Also a regression test for /get_allowed_conflations, which returned HTTP 500 until the previous commit: it mounts just that handler and validates the body against the documented ConflationList schema. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
It ran only against the su10 Elasticsearch host before. This mounts the handler alone with a fake Elasticsearch client and validates the body against the documented schema. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dot in each redirect pattern was unescaped, so /openapiXjson and /faviconXico redirected too. The OpenTelemetry exclusions already escape it. A test now checks the /openapi.json redirect and that a near-miss path is a 404. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ment
The query-parameter check scanned only get() for get_argument calls, so
a parameter read in a helper method would drift unnoticed; it now scans
the whole handler class. A new check compares the fields each post()
reads with .get("...") against the properties of the documented request
body (CurieList, and the SetIDQuery items of the /get_setid array).
Both were confirmed to fail when a field is removed from the document or
a parameter is renamed in a helper.
The checks still only see literal names; the README now says so.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/openapi.json redirected to /webapp/openapi.json. It now serves the document itself, which is where NodeNorm Redis (FastAPI's default) and most Translator services serve theirs, and the Swagger UI at / loads it from there. /webapp/openapi.json keeps working through the existing /webapp asset handler, because Babel Validation's targets.ini and the Translator diagram's nodenorm-es component are configured with that address. Removing it would break them and gain nothing; they can switch to the default once this is deployed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on #42 — review only the last commit, "Serve the OpenAPI document at /openapi.json". Until #42 merges, this PR's diff against
mainincludes it.#42 makes
/openapi.jsonredirect to/webapp/openapi.json. This PR serves the document at/openapi.jsondirectly instead, which is where NodeNorm Redis (FastAPI's default) and most Translator services serve theirs, and points the Swagger UI at/there. Clients that fetch/openapi.jsonget the document without following a redirect, and the root address becomes the canonical one.Calls worth overruling
/webapp/openapi.jsonkeeps working. It costs nothing, because the existing/webapp/(.*)asset handler already serves the file. Babel Validation'stests/targets.inisetsNodeNormOpenAPIPath = webapp/openapi.jsonfor the ES deployments, and the Translator diagram'scomponents/nodenorm-es.yamldoes the same, so removing that address would break both. Once this is deployed, both can drop the override and use the default.src/nodenorm/webapp/openapi.json. Only the route changes;/statusand the tests read the file there, so moving it would only add churn.For the reviewer
The same change could be applied to NameRes ES (
biothings/NameResolutionAPI), which has the same/webapplayout and serves its document only at/webapp/openapi.json, unlike NameRes Redis. The node annotator is in the same position. This PR changes only NodeNorm ES. If you'd like NameRes ES to match, it would be a separate PR in that repository (which could also escape the dot in its/favicon.icoroute, as #42 does here), and the Translator diagram'scomponent-metadata.md, which currently callswebapp/openapi.jsonthe intended convention for these services, would need updating too.Verification
On e33e84d, the host-free tests (
test_openapi.py,test_cors.py,test_health.py,test_version.py) pass. They check that both addresses return the document with a JSON content type, that/openapiXjsonis a 404, and that the Swagger UI loads/openapi.json. The Swagger UI wasn't opened in a browser.🤖 Generated with Claude Code