Skip to content

Self-host Swagger UI assets (remove cdn.jsdelivr.net dependency from /docs) #197

Description

@oto-macenauer-absa

Summary

PR #190 adds a GET /docs endpoint that serves a Swagger UI page. The page currently loads Swagger UI assets from a public CDN:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css">
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js"></script>

Depending on cdn.jsdelivr.net at runtime is undesirable:

  • Availability — the docs page breaks whenever the CDN is unreachable (air-gapped / VPC-only deployments, CDN outage, corporate egress filtering).
  • Supply chain — a compromised or hijacked CDN response executes arbitrary JS in the browser of anyone viewing the docs. No SRI hash pins the content.
  • Reproducibility — the served asset version can drift under the @5 major tag without any change to our image.

We should vendor the Swagger UI static assets, bake them into the Docker image, and serve them from the Lambda so /docs is fully self-hosted with zero external requests.

Background

  • Docs handler: src/handlers/handler_api.pyget_docs() (returns the HTML string).
  • Routing: src/event_gate_lambda.py ROUTE_MAP, dispatched by exact API Gateway resource field via src/utils/utils.py::dispatch_request.
  • Assets already baked into the image are COPYed in Dockerfile (see COPY api.yaml $LAMBDA_TASK_ROOT/api.yaml).
  • Only two files are strictly required from swagger-ui-dist@5: swagger-ui.css (~145 KB) and swagger-ui-bundle.js (~1.4 MB, self-contained — includes presets). Both are well under the 6 MB API Gateway Lambda-proxy response limit.
  • Swagger UI is Apache-2.0 licensed — compatible with this project.

Proposed work

1. Vendor the assets

Add pinned Swagger UI assets to the repo, e.g. src/static/swagger-ui/:

  • swagger-ui.css
  • swagger-ui-bundle.js

Pin the exact version (e.g. swagger-ui-dist@5.x.y, not floating @5). Record the version + upstream source + license in a short README/NOTICE next to the files so future upgrades are traceable.

Alternative: download+checksum-verify during the Docker build instead of committing binaries. Committing is simpler, deterministic, and needs no build-time network — recommended unless the team prefers to keep vendored blobs out of git.

2. Serve the assets from the Lambda

Add handler methods that read the vendored files and return them with correct Content-Type (text/css, application/javascript). Register routes in ROUTE_MAP, e.g.:

  • /docs/swagger-ui.css
  • /docs/swagger-ui-bundle.js

(or a single /docs/{proxy+} catch-all dispatching by filename — fewer API Gateway resources to declare). Consider a long-lived Cache-Control header since assets are version-pinned.

3. Point the page at the local assets

Update get_docs() HTML to use relative paths instead of the CDN URLs:

<link rel="stylesheet" href="./docs/swagger-ui.css">
<script src="./docs/swagger-ui-bundle.js"></script>

Relative paths keep working across all API Gateway stages / custom domains (same rationale as the existing ./api reference).

4. Bake assets into the image

Add a COPY src/static $LAMBDA_TASK_ROOT/src/static (or the chosen path) to the Dockerfile, and ensure the non-root app user has read access (the existing chown -R 1000:1000 ... ${LAMBDA_TASK_ROOT} already covers files under the task root).

5. Tests + docs

  • Unit: new asset routes return 200, correct Content-Type, non-empty body; /docs HTML references relative ./docs/... paths and no longer contains cdn.jsdelivr.net.
  • Integration: extend EventGateTestClient / tests/integration/test_api_endpoint.py.
  • api.yaml: document the asset routes (or the {proxy+}).

Deployment note

Like /docs itself (see PR #190), the API Gateway must route the new asset path(s) to the EventGate Lambda (explicit resources or a {proxy+} catch-all). This requires a matching infra change in cps-eventbus-gateway.

Acceptance criteria

  • /docs renders Swagger UI with no requests to cdn.jsdelivr.net or any external host (verifiable via browser network tab / offline).
  • Swagger UI assets are version-pinned and vendored into the Docker image.
  • Asset version, source, and license are recorded.
  • Unit + integration tests cover the new asset routes and the CDN-free HTML.

Related: PR #190, #191

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions