X-Forwarded-Host packs path + Proto defaults to https; breaks editor on non-mycelium clients #16

Closed
opened 2026-04-27 09:30:59 +00:00 by zaelgohary · 0 comments
Member

Symptom

When the editor wrapper is loaded via any non-mycelium path (mac via SSH tunnel, public IP, etc), OnlyOffice's runtime fetches for Editor.bin come back from https://<host>:9988/hero%5foffice/ui/onlyoffice/cache/files/data/<key>/Editor.bin. Two defects in the URL:

  • https:// (page is HTTP)
  • %5f (URL-encoded underscore)

Browser tries the URL → ERR_SSL_PROTOCOL_ERROR against an HTTP-only stack → editor renders shell but document body never loads.

Cause

crates/hero_office_ui/src/handlers.rs::forward_to_onlyoffice (lines ~864–875) packs a path into X-Forwarded-Host and defaults X-Forwarded-Proto to https:

let public_proto = headers
    .get("x-forwarded-proto").and_then(|v| v.to_str().ok())
    .unwrap_or("https");                       // <- wrong default for HTTP gateways
let oo_external = format!("{}/hero_office/ui/onlyoffice", public_host);
.header("X-Forwarded-Host", oo_external)        // <- non-standard, OO URL-encodes

OnlyOffice URL-encodes oo_external when embedding it in cache URLs (treating it as a host). The _ becomes %5f. The default-https is also wrong for any HTTP-only deployment.

Why it didn't surface earlier

  • Yesterday's playwright tests only assert the editor shell renders (toolbar text). The cache fetch path runs after the shell — never validated.
  • Real Chrome enforces mixed-content; headless chromium tolerates it.
  • From herodev's own browser, OnlyOffice's runtime would default to its own listen address (mycelium IP) which is reachable locally — bypassing the broken proxy URL entirely.

Acceptance

  • X-Forwarded-Host only contains host:port (no path).
  • X-Forwarded-Prefix: /hero_office/ui/onlyoffice carries the path.
  • X-Forwarded-Proto defaults to http when the original incoming request is plain HTTP (or hero_router sets it explicitly).
  • OnlyOffice's internal nginx config respects X-Forwarded-Prefix for cache URL generation. May require a local.json override baked into the docker container or service_onlyoffice.nu.
  • e2e: open a doc via mac browser through the SSH tunnel; verify Editor.bin fetches succeed and the document body renders.
## Symptom When the editor wrapper is loaded via any non-mycelium path (mac via SSH tunnel, public IP, etc), OnlyOffice's runtime fetches for `Editor.bin` come back from `https://<host>:9988/hero%5foffice/ui/onlyoffice/cache/files/data/<key>/Editor.bin`. Two defects in the URL: - `https://` (page is HTTP) - `%5f` (URL-encoded underscore) Browser tries the URL → `ERR_SSL_PROTOCOL_ERROR` against an HTTP-only stack → editor renders shell but document body never loads. ## Cause `crates/hero_office_ui/src/handlers.rs::forward_to_onlyoffice` (lines ~864–875) packs a path into `X-Forwarded-Host` and defaults `X-Forwarded-Proto` to `https`: ```rust let public_proto = headers .get("x-forwarded-proto").and_then(|v| v.to_str().ok()) .unwrap_or("https"); // <- wrong default for HTTP gateways let oo_external = format!("{}/hero_office/ui/onlyoffice", public_host); .header("X-Forwarded-Host", oo_external) // <- non-standard, OO URL-encodes ``` OnlyOffice URL-encodes `oo_external` when embedding it in cache URLs (treating it as a host). The `_` becomes `%5f`. The default-https is also wrong for any HTTP-only deployment. ## Why it didn't surface earlier - Yesterday's playwright tests only assert the editor *shell* renders (toolbar text). The cache fetch path runs after the shell — never validated. - Real Chrome enforces mixed-content; headless chromium tolerates it. - From herodev's own browser, OnlyOffice's runtime would default to its own listen address (mycelium IP) which is reachable locally — bypassing the broken proxy URL entirely. ## Acceptance - `X-Forwarded-Host` only contains host:port (no path). - `X-Forwarded-Prefix: /hero_office/ui/onlyoffice` carries the path. - `X-Forwarded-Proto` defaults to `http` when the original incoming request is plain HTTP (or `hero_router` sets it explicitly). - OnlyOffice's internal nginx config respects `X-Forwarded-Prefix` for cache URL generation. May require a `local.json` override baked into the docker container or `service_onlyoffice.nu`. - e2e: open a doc via mac browser through the SSH tunnel; verify `Editor.bin` fetches succeed and the document body renders.
Sign in to join this conversation.
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#16
No description provided.