feat: themed API docs and versioned route namespace - #18
Merged
Conversation
Restructure the docs surface and the route namespace. Docs: serve Swagger UI from vendored assets instead of a CDN, themed to match ckanext-openapidocs so both sets of docs read as one family. The page is a Jinja template; branding comes from DOCS_* env vars, validated as CSS colours since they land in a <style> block. All docs concerns moved out of main.py into api/docs.py (327 -> 77 lines). Routes: actions are versioned at /datastore/api/v2/, while health probes and downloads sit unversioned at /datastore/api/ so probe URLs and download links survive a contract bump. info.version now carries the API contract version rather than the package build version -- the two are independent. Also removes the welcome endpoint and its APP_MESSAGE config.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
`help` echoed the request URL back, which told the caller nothing they hadn't just typed. It now deep-links into Swagger UI at the operation that served the request, so every response — errors included — points at the documentation for the endpoint you called. Operation ids are derived from the handler names, so the anchors read as `#/Datastore/datastore_search` rather than FastAPI's generated `datastore_search_datastore_api_v2_datastore_search_get`. That also gives generated client SDKs sane method names. Unrouted requests fall back to the request URL, since a 404 has no operation to link to.
The `ErrorEnvelope` example hardcoded its host. It is now composed from `API_URL` and `API_PREFIX` in `core/constants.py`, so the example can't drift out of sync with the paths the service actually serves. Both live in constants rather than config because `schemas/` builds the string and may not import config. Runtime `help` values are unaffected — those come from the incoming request, so they stay correct behind a proxy.
Adds an `API_URL` setting (default https://example.com) so a deployment's published examples show its own host instead of a placeholder. `schemas/` declares the example with a relative path, since it may not read config; `api/docs.py` fills in the host when the schema is built. Runtime `help` values are untouched — those come from the incoming request, so they stay correct behind a proxy or on any host.
Resolves tests/auth/test_orchestration.py: `authorize` always returns a "user" key, so the incoming assertion was the correct one; kept HEAD's formatting to match the rest of the file. The merge also had a conflict git could not see. The analytics middleware matched `/api/3/action/` and `/datastore/dump/`, both of which this branch had moved, so it silently recorded nothing — analytics would have gone dark in production, not just in tests. Its prefixes now derive from API_PREFIX / API_BASE_PREFIX, as do the analytics tests' URLs. Excluding the docs surface then had to become explicit: docs, redoc, openapi.json and static now sit *inside* the versioned prefix, so they matched the action pattern and were recorded as actions named "docs", "redoc", and so on. Sitting outside `/api/3/action/` used to exclude them for free.
sagargg
added a commit
that referenced
this pull request
Aug 19, 2026
* feat: themed API docs and versioned route namespace Restructure the docs surface and the route namespace. Docs: serve Swagger UI from vendored assets instead of a CDN, themed to match ckanext-openapidocs so both sets of docs read as one family. The page is a Jinja template; branding comes from DOCS_* env vars, validated as CSS colours since they land in a <style> block. All docs concerns moved out of main.py into api/docs.py (327 -> 77 lines). Routes: actions are versioned at /datastore/api/v2/, while health probes and downloads sit unversioned at /datastore/api/ so probe URLs and download links survive a contract bump. info.version now carries the API contract version rather than the package build version -- the two are independent. Also removes the welcome endpoint and its APP_MESSAGE config. * feat: point envelope `help` at the endpoint's docs `help` echoed the request URL back, which told the caller nothing they hadn't just typed. It now deep-links into Swagger UI at the operation that served the request, so every response — errors included — points at the documentation for the endpoint you called. Operation ids are derived from the handler names, so the anchors read as `#/Datastore/datastore_search` rather than FastAPI's generated `datastore_search_datastore_api_v2_datastore_search_get`. That also gives generated client SDKs sane method names. Unrouted requests fall back to the request URL, since a 404 has no operation to link to. * refactor: build the schema example URL from constants The `ErrorEnvelope` example hardcoded its host. It is now composed from `API_URL` and `API_PREFIX` in `core/constants.py`, so the example can't drift out of sync with the paths the service actually serves. Both live in constants rather than config because `schemas/` builds the string and may not import config. Runtime `help` values are unaffected — those come from the incoming request, so they stay correct behind a proxy. * feat: make the OpenAPI example host configurable via API_URL Adds an `API_URL` setting (default https://example.com) so a deployment's published examples show its own host instead of a placeholder. `schemas/` declares the example with a relative path, since it may not read config; `api/docs.py` fills in the host when the schema is built. Runtime `help` values are untouched — those come from the incoming request, so they stay correct behind a proxy or on any host. * Fix: re-formatting
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.
Restructures the docs surface and the route namespace.
Docs
Swagger UI is now served from vendored assets rather than a CDN, so
/datastore/api/v2/docsrenders with no outbound network. The theme is ported fromckanext-openapidocsso this service's docs and the CKAN portal's read as one family.The page is a Jinja template (
api/templates/docs.html). Branding comes fromDOCS_PRIMARY_COLOR/DOCS_HEADER_COLOR/DOCS_SITE_TITLE/DOCS_LOGO_URL; the colours are validated as CSS colours at startup since they land inside a<style>block.All docs concerns moved out of
main.pyintoapi/docs.py, takingmain.pyfrom 327 to 77 lines — it's now just the app factory and lifespan.Routes
Breaking. Actions move from
/api/3/action/to/datastore/api/v2/:/datastore/api/v2/datastore_*/datastore/api/health·/datastore/api/ready/datastore/api/dump/query·/datastore/api/dump/{resource_id}Probes and downloads sit outside the version deliberately: an orchestrator's probe URL and a download link shouldn't churn when the action contract gets a new version.
info.versionnow carries the API contract version (v2), not the package build (0.2.0). The two are independent — the app can ship any number of releases without the contract changing.Response
helpThe envelope's
helpfield echoed the request URL back — no use to a caller who just typed it. It now deep-links into Swagger at the operation that served the request, so every response, errors included, points at that endpoint's docs:Operation ids are derived from the handler names, so anchors read as
#/Datastore/datastore_searchrather than FastAPI's generateddatastore_search_datastore_api_v2_datastore_search_get. Generated client SDKs get sane method names as a side effect.Also
GET /) and its now-deadAPP_MESSAGEconfig. The root returns 404./healthand would otherwise have restart-looped on deploy.Notes for reviewers
ckan_client.pyandauth/ckan/provider.pystill call upstream CKAN's own/api/3/action/— only this service's routes moved..envcan't leak into assertions.