Skip to content

fix(js): keep attachment urls and repoint images across http restarts - #29674

Merged
chrisnojima merged 6 commits into
nojima/HOTPOT-js-03-appstatefrom
nojima/HOTPOT-js-04-httpsrv
Sep 23, 2026
Merged

chrisnojima merged 6 commits into
nojima/HOTPOT-js-03-appstatefrom
nojima/HOTPOT-js-04-httpsrv

Conversation

@chrisnojima

Copy link
Copy Markdown
Contributor

Stack 2/7 on #29650.

Why

The service stops its local http server when the app backgrounds and starts it again when the app returns. The address can change on a restart, and a restarted service process also issues a new token. On master (#29665):

  • Attachments go blank after a background trip. A message unboxed while the server is stopped arrives with an empty or base-less fileURL/previewURL. The thread merge copies that over the good URL, so the image stays broken until the conversation is reloaded.
  • A failed image never recovers. The retry only appends a cache-buster to the old address and token, so an image with a stale port or token keeps failing.

What this changes

  • localhost-src.tsx (new): on retry, a src pointing at the service's own endpoints (/at, /av, /map) is repointed at the current config.httpSrv address and has its token= rewritten. Every other localhost src, including KBFS's /files/ server, which has its own port and token, still gets only the cache-buster.
  • image.tsx: the retry computes the rewritten src when it is scheduled, reading httpSrv from the store at that moment rather than subscribing every image to it.
  • thread-message-state.tsx: when a message merges, fileURL and previewURL keep the existing value unless the incoming one is a real http:// URL.

Judgment calls

  • Emoji reaction decorations are deliberately not protected. Custom emoji URLs reach JS inside base64 decoration payloads in ReactionDesc.decorated, never as a bare URL. Guarding the whole field would freeze reactions after their first value, and rewriting inside the payload is out of proportion for a workaround. A custom emoji unboxed while the server is stopped renders broken until its message reloads. The Go fix in test(kbhttp): failing tests for server lifetime across app states #29665 covers it at the source.
  • image.tsx keeps master's mobileAppState !== 'active' retry guard, so retries wait until the app is active.
  • Only http:// counts as a real URL. An update carrying some other http:// value would still replace the field. That is no looser than master, which took every value as-is.

Tests

  • localhost-src.test.ts: only localhost srcs retry; a retry repoints the port, replaces the token (also on a same-port restart), keeps the baked address when the current one is unknown, and leaves a KBFS src on its own server and token.
  • thread-message-state.test.tsx has a table over fileURL and previewURL: an empty value keeps the existing URL, a base-less value keeps it, and a real URL replaces it. This inverts master's "an empty url overwrites" expectation.

@chrisnojima
chrisnojima added this pull request to stack #29680 September 23, 2026 19:54
@chrisnojima
chrisnojima removed this pull request from stack #29680 September 23, 2026 19:56
@chrisnojima
chrisnojima added this pull request to stack #29681 September 23, 2026 19:56
@chrisnojima
chrisnojima merged commit 9ac2be6 into master Sep 23, 2026
1 check passed
@chrisnojima
chrisnojima deleted the nojima/HOTPOT-js-04-httpsrv branch September 23, 2026 20:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant