Route applications by host/urlPath in the root config - #612
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the documentation for middleware routing, detailing application-level routing via the root harper-config.yaml or deploy-time parameters, and how it composes with plugin-level routing. It also clarifies host-matching behavior, such as case-insensitivity and IPv6 formatting. The review feedback recommends using a relative link instead of an absolute versioned link in the operations API documentation to prevent future version-pinning issues.
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-612 This preview will update automatically when you push new commits. |
1 similar comment
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-612 This preview will update automatically when you push new commits. |
|
Addressed @cb1kenobi's feedback on — KrAIs (Claude Sonnet 5) |
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-612 This preview will update automatically when you push new commits. |
Ethan-Arrowood
left a comment
There was a problem hiding this comment.
Cross-checked against harper#1964. The substance is accurate — mount-strip semantics, per-environment remounting, the harper deploy … host= urlPath= example, the payload-deploy rejection note, bare-IPv6 forms in all three files, and the resource-registry caveat all verified, and correcting the previously-documented case-sensitive host matching is a good catch.
Two things before merge, one of them a hold.
Hold behind #1964. I reviewed that PR earlier today and raised two findings that bear directly on this text: host-mounted apps currently don't match under HTTP/2 (matchesRoute never reads :authority), and a hand-edited root-config host is never validated. If the h2 gap gets fixed in core, this doc needs no change; if h1-only is accepted as a design limitation, these docs must say so. Worth re-reading the two host-matching sentences (api.md:51, overview.md:77) once #1964 settles.
Minor: link style is inconsistent between two of the touched files — operations.md:609 uses ../http/overview.md#middleware-routing while plugin-api.md:47 uses extensionless ../http/overview#middleware-routing. Build passes either way; extensionless matches the surrounding files.
sent with Claude Opus 5
|
|
||
| - **It does not namespace resources.** Exported tables live in one instance-wide registry, so a table exported by one application is reachable through any mounted REST route, not only its own. | ||
| - **It does not constrain legacy Fastify routes by host.** `fastifyRoutes` registers as a global fallback outside the routed middleware chain, so those routes answer on every hostname. A `urlPath` mount does apply (it becomes the Fastify route prefix); a `host` mount does not, and Harper refuses to load a host-mounted application that declares `fastifyRoutes` rather than silently serving it unconstrained. Port them to `server.http()` for host routing. | ||
|
|
There was a problem hiding this comment.
This overstates the failure scope. fastifyRoutes.ts does throw in #1964, but the loader's catch is per plugin inside the app's config loop (componentLoader.ts#L737) — it marks the fastifyRoutes component failed and continues; the code comment says as much ("contained to this component by the loader's per-component try/catch, so it does not take down the rest of the application"). So the app's other handlers (rest, static, …) still load and serve on the host mount; only the legacy routes fail.
As written, a reader expects the whole app to refuse to start and would misdiagnose a partially-running app — the same class of mismatch @cb1kenobi already caught once in the opposite direction (docs said "warns", code throws). Suggested wording: "Harper fails the application's fastifyRoutes with a load error rather than silently serving them unconstrained; the application's other handlers still load."
Follow-up to #595. That PR documented `host`/`urlPath` as a component-`config.yaml` setting, which described the mechanism but put the routing in the wrong place: where an application is served is a deployment concern, and a value checked into the application cannot be remapped per environment (the env-config overlay is root-config-only). Harper now treats the application's root-config entry as authoritative (HarperFast/harper PR pending), so lead with that placement: - `reference/http/overview.md` — mount an application from the root `harper-config.yaml`; a plugin's own `urlPath` positions it within the app and the mount is prefixed onto it, while a root-config `host` overrides one the app shipped. - `reference/components/plugin-api.md` — scope the plugin-level options to "within the application" and point at the root-config mount. - `reference/operations-api/operations.md` — document `host` on `deploy_component` and note that both it and `urlPath` are persisted to the root-config entry. - 5.2 release notes — lead with the application mount.
Follows the cross-model review of the core change: - A mount is a routing prefix, not an isolation boundary. Exported tables are instance-wide, so a table exported by one application is reachable through any mounted REST route. - Legacy `fastifyRoutes` register as a global fallback outside the routed chain, so a `host` mount cannot constrain them (a `urlPath` mount does apply). Harper warns in that case. - Host matching is case-insensitive, not case-sensitive as `HttpOptions` previously documented — hostnames are case-insensitive (RFC 4343) and clients send them lowercased, so the old behavior made a configured `API.example.com` unmatchable. - IPv6 hosts are configured as a bare literal, not bracketed; `urlPath` rejects `.` segments.
Addresses PR review:
- `deployComponentValidator` declares `.with('urlPath','package').with('host','package')`, so
both are rejected on a payload-only deploy. The "Additional parameters" list implied
otherwise; state the requirement and point payload deploys at the root-config entry.
- Badge the new `host` parameter with v5.2.0 per the versioning rule.
- Use a relative link for the middleware-routing reference, matching the rest of the file
(21 relative links vs the one absolute one this PR introduced).
harper#1964's handleApplication throws when a host-mounted application declares fastifyRoutes, and componentLoader.ts catches it and marks the component failed — it doesn't continue running with a warning logged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
89ec9b6 to
453f1d0
Compare
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-612 This preview will update automatically when you push new commits. |
Summary
Follow-up to Document middleware host and path routing (#595), which is already merged.
#595 documented
host/urlPathas a component-config.yamlsetting. That described the mechanism accurately but put the routing in the wrong place: where an application is served is a deployment concern, and a value checked into the application can't be remapped per environment (the env-config overlay is root-config-only). On a root-config application entry those keys were also silently inert.Core now treats the application's root-config entry as authoritative — Route applications by host/urlPath declared in the root config (HarperFast/harper#1964) — so these docs lead with that placement.
Changes
reference/http/overview.md— mount an application from the rootharper-config.yaml; a plugin's ownurlPathpositions it within the app and the mount is prefixed onto it; a root-confighostoverrides one the app shipped. Adds a "what a mount does not do" section: it is not a resource namespace, and it cannot constrain legacy Fastify routes by host.reference/http/api.md—hostmatching is case-insensitive, not case-sensitive as previously documented. Hostnames are case-insensitive (RFC 4343) and clients send them lowercased, so the old behavior made a configuredAPI.example.comunmatchable; core fixed the compare. Also notes bare (unbracketed) IPv6 literals.reference/operations-api/operations.md— documentshostondeploy_componentand the accepted forms for both it andurlPath.Note
The
HttpOptionscase-sensitivity correction describes behavior that changes in harper#1964, so this shouldn't merge ahead of it.npm run format:checkandnpm run buildpass (one pre-existing broken anchor in the 5.1 release notes, unrelated).Generated by Claude Opus 5.