fix(office_ui): proper X-Forwarded headers + same-origin api.js bootstrap #17

Merged
zaelgohary merged 1 commit from development_fix_office_ui_xforwarded_headers into development 2026-04-27 10:12:29 +00:00
Member

Summary

Editor now bootstraps from any client that can reach hero_router — no need for a direct route to the OnlyOffice container (mycelium / public IP). Three corresponding fixes inside hero_office_ui:

  1. X-Forwarded-Host carries only host:port (RFC 7239 compliant); path-prefix moves to a separate X-Forwarded-Prefix header. Previously the prefix was packed into X-Forwarded-Host and OnlyOffice URL-encoded the underscore (_%5f), mangling every cache URL it generated.
  2. X-Forwarded-Proto defaults to http (was https). Every Hero deployment we run today is HTTP at the hero_router layer.
  3. Editor wrapper page injects <script src="$prefix/onlyoffice/web-apps/...api.js"> (same-origin) instead of <script src="$OO_SERVER_URL/..."> (direct OO). Browsers can bootstrap DocsAPI through the proxy without a route to OnlyOffice.

Closes #16

Changes

  • crates/hero_office_ui/src/handlers.rs — semantic fix (X-Forwarded-* + same-origin api.js); also 11 mechanical clippy 1.94 fixes (collapsible_if, useless_conversion)
  • crates/hero_office_ui/src/{config,main,state}.rs — fmt drift cleanup (unblocks /ci-check)

Test Results

  • cargo fmt --check -- crates/hero_office_ui/src/handlers.rs
  • cargo check --workspace
  • cargo clippy -p hero_office_ui -- -D warnings
  • npx playwright test office_editor_real 4/4 (regression unchanged)

Manual verification

Editor loads + document body renders end-to-end from a mac browser via SSH tunnel (ssh -N -L 9988:127.0.0.1:9988 herodevhttp://127.0.0.1:9988/hero_os/ui/). Previous behaviour: ERR_ADDRESS_UNREACHABLE on api.js, then ERR_SSL_PROTOCOL_ERROR / mangled cache URLs. New behaviour: editor renders.

Caveat

Change #2 affects future HTTPS-fronted deployments. When we eventually put TLS in front of hero_router, the gateway must explicitly set X-Forwarded-Proto: https — same as any other reverse-proxy setup.

## Summary Editor now bootstraps from any client that can reach hero_router — no need for a direct route to the OnlyOffice container (mycelium / public IP). Three corresponding fixes inside `hero_office_ui`: 1. `X-Forwarded-Host` carries only host:port (RFC 7239 compliant); path-prefix moves to a separate `X-Forwarded-Prefix` header. Previously the prefix was packed into `X-Forwarded-Host` and OnlyOffice URL-encoded the underscore (`_` → `%5f`), mangling every cache URL it generated. 2. `X-Forwarded-Proto` defaults to `http` (was `https`). Every Hero deployment we run today is HTTP at the hero_router layer. 3. Editor wrapper page injects `<script src="$prefix/onlyoffice/web-apps/...api.js">` (same-origin) instead of `<script src="$OO_SERVER_URL/...">` (direct OO). Browsers can bootstrap DocsAPI through the proxy without a route to OnlyOffice. ## Related Issue Closes #16 ## Changes - `crates/hero_office_ui/src/handlers.rs` — semantic fix (X-Forwarded-* + same-origin api.js); also 11 mechanical clippy 1.94 fixes (collapsible_if, useless_conversion) - `crates/hero_office_ui/src/{config,main,state}.rs` — fmt drift cleanup (unblocks `/ci-check`) ## Test Results - `cargo fmt --check -- crates/hero_office_ui/src/handlers.rs` ✅ - `cargo check --workspace` ✅ - `cargo clippy -p hero_office_ui -- -D warnings` ✅ - `npx playwright test office_editor_real` 4/4 ✅ (regression unchanged) ## Manual verification Editor loads + document body renders end-to-end from a mac browser via SSH tunnel (`ssh -N -L 9988:127.0.0.1:9988 herodev` → `http://127.0.0.1:9988/hero_os/ui/`). Previous behaviour: `ERR_ADDRESS_UNREACHABLE` on api.js, then `ERR_SSL_PROTOCOL_ERROR` / mangled cache URLs. New behaviour: editor renders. ## Caveat Change #2 affects future HTTPS-fronted deployments. When we eventually put TLS in front of hero_router, the gateway must explicitly set `X-Forwarded-Proto: https` — same as any other reverse-proxy setup.
8 handlers (health, list_contexts, list_documents, create_editor_session,
get_document, save_document, upload_document, delete_document) now emit
tracing spans automatically — entry, exit, and timing show up in the
existing tracing pipeline at INFO level (RUST_LOG=info,hero_office_server=debug).

Foundation for #14. Future work: hook a metrics exporter onto these spans
so we can answer how many editor sessions per day, save-latency p95, etc.
X-Forwarded-Host now carries only host:port per RFC 7239, with the
path-prefix sent via the standard X-Forwarded-Prefix header. Previously
the prefix was packed into X-Forwarded-Host; OnlyOffice URL-encoded the
underscore (_ → %5f) when embedding it in cache URLs, breaking every
runtime fetch from non-mycelium browsers.

X-Forwarded-Proto now defaults to "http" instead of "https". Every
Hero deployment we run today is HTTP at the hero_router layer; the old
default forced OnlyOffice to emit https:// URLs that ERR_SSL_PROTOCOL_ERROR
against an HTTP-only stack. Future HTTPS-fronted deployments must set
X-Forwarded-Proto: https at the gateway.

Editor wrapper page now loads OnlyOffice api.js via the same-origin proxy
path ($prefix/onlyoffice/web-apps/...) instead of OO_SERVER_URL directly.
Browsers reaching hero_router via SSH tunnel or any non-mycelium path can
now bootstrap the editor without needing a route to the OnlyOffice
container.

Drive-by: clippy 1.94 in CI flagged 11 pre-existing collapsible_if /
useless_conversion warnings + fmt drift on 3 sibling files; all fixed
mechanically via cargo clippy --fix + cargo fmt to unblock /ci-check.

Closes #16
zaelgohary merged commit 720ae4c53d into development 2026-04-27 10:12:29 +00:00
zaelgohary deleted branch development_fix_office_ui_xforwarded_headers 2026-04-27 10:12:30 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_office!17
No description provided.