# `PhoenixKitWeb.PdfViewerController`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.165/lib/phoenix_kit_web/controllers/pdf_viewer_controller.ex#L1)

Serves `phoenix_kit_catalogue`'s vendored PDF.js viewer assets through
the router.

The catalogue PDF detail page embeds the viewer from `/_pdfjs/...`.
Normally those bytes are served by a `Plug.Static` mount that
`mix phoenix_kit.install` / `mix phoenix_kit.update` add to the host
endpoint. That mount is fragile — a host that bumps the deps without
re-running the task (or whose endpoint gets regenerated by a scaffold
script) loses it, and the viewer iframe then 404s with a
`NoRouteError`.

This controller is the router-served fallback. Because it's wired in
via `phoenix_kit_routes()` (the same mechanism behind `/file/...` and
`/<prefix>/assets/...`), it's present on every host that mounts
PhoenixKit at all — no endpoint patch required. When the endpoint
`Plug.Static` mount *is* present it runs first (endpoint plugs precede
the router), so this only handles the fall-through.

Read-only: it streams files from the catalogue app's
`priv/static/pdfjs/` and nothing else. Path traversal is rejected via
`Path.safe_relative/1` plus an expanded-prefix check.

## Compatibility note

The route is mounted at the **root** literal `/_pdfjs/*path` (no URL
prefix / locale) so it matches the same URL the catalogue's iframe and
the endpoint `Plug.Static` mount use. A host app that already serves its
own `/_pdfjs/...` would shadow / be shadowed here — but the path is
deliberately underscore-prefixed and module-namespaced to avoid
collisions, and the route only compiles in when `phoenix_kit_catalogue`
is a dependency.

# `serve`

Streams a single vendored PDF.js asset by its path under
`priv/static/pdfjs/`. 404s on traversal attempts, a missing
catalogue app, or a non-file target.

Sends an `ETag` and honours `If-None-Match` (304) so browsers can
revalidate cheaply instead of re-downloading every asset once the
`max-age` window lapses.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
