anvilsign in

collin/anvil · 8887ef61

Render htmx error responses instead of dropping them

Collin Richards · 2026-08-18 10:08 UTC · 8887ef61772f5a23435d650a81bd1e0e560b4f4f · parent 2f49cc06 · browse files

modifiedcrates/anvil-web/src/ui.rs+16 −0
⋯ 349 unchanged lines
350350
351351 /// Delegated handlers for the clone widget: protocol toggle + copy-to-clipboard.
352352 /// Registered once on `document`, so it survives htmx body swaps.
353+/// Make htmx render error responses instead of discarding them.
354+///
355+/// Handlers answer a rejected form with the page *and* the reason — a bad
356+/// password, an unparseable ssh key — under a 4xx status. htmx's default
357+/// `responseHandling` swaps only 2xx, so with `hx-boost` on the body every one
358+/// of those pages was silently dropped and the button looked broken. Without
359+/// JavaScript the same responses always rendered fine, which is why this hid.
360+const HTMX_CONFIG_JS: &str = r#"
361+htmx.config.responseHandling = [
362+ { code: "204", swap: false },
363+ { code: "[23]..", swap: true },
364+ { code: "[45]..", swap: true, error: true },
365+];
366+"#;
367+
353368 const CLONE_JS: &str = r#"
354369 (function(){
355370 function copyText(t){
⋯ 116 unchanged lines
472487 main { div.container { (body) } }
473488 footer { div.container { "anvil — a git forge" } }
474489 script src="/-/static/htmx.min.js" {}
490+ script { (PreEscaped(HTMX_CONFIG_JS)) }
475491 script { (PreEscaped(CLONE_JS)) }
476492 }
477493 }
⋯ 2363 unchanged lines