Media build part 2 (unreleased): drive wiring in every app (R-1024/R-1037), old-install repair (R-1047), drive events notice + real restart now/later + stream check, file browser lets go of dead/removed drives and recreates on return (R-1038), safe removal keeps the drive (R-1044), Plex claim on the running server + probe accept (R-1028/R-1045)
gates / gates (push) Successful in 45s

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-15 09:54:49 +02:00
parent 78c894234c
commit f580d88a14
46 changed files with 3700 additions and 8 deletions
+25 -1
View File
@@ -50,6 +50,9 @@ type SetupDoneProbe struct {
Done string `yaml:"done" json:"done"`
// DoneStatus (v0.282.0, R-715): a non-200 HTTP status that itself means "set up" (gramps-web answers 405).
DoneStatus int `yaml:"done_status,omitempty" json:"done_status,omitempty"`
// Accept (v0.313.0, R-1028/R-1045): the Accept header the probe sends — Plex answers /identity in XML unless asked
// for JSON (measured 2026-10-15). Empty = no header (unchanged for every other app).
Accept string `yaml:"accept,omitempty" json:"accept,omitempty"`
}
// Setup gate states.
@@ -380,12 +383,33 @@ var setupGateProbeFetch = func(url string) (int, []byte, error) {
return resp.StatusCode, b, err
}
// setupGateProbeFetchAccept is setupGateProbeFetch with an Accept header (a seam too).
var setupGateProbeFetchAccept = func(url, accept string) (int, []byte, error) {
c := &http.Client{Timeout: 5 * time.Second}
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return 0, nil, err
}
req.Header.Set("Accept", accept)
resp, err := c.Do(req)
if err != nil {
return 0, nil, err
}
defer resp.Body.Close()
b, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
return resp.StatusCode, b, err
}
// probeOnce asks the app's own status once. v0.282.0 (R-715): `done_status:` — an app that answers a fixed non-200
// status once it is set up (gramps-web: 405 "Users already exist") — counts as done on that status alone; any other
// non-200 is "cannot read" (fail closed). A 200 is read as JSON: `field` is a dotted path whose parts may be list
// indexes (`setup.0.status` — ghost; `0.done` — home-assistant), compared as text with `done`.
func probeOnce(p *SetupDoneProbe) (done bool, got string, err error) {
status, body, err := setupGateProbeFetch(p.URL)
fetch := setupGateProbeFetch
if p.Accept != "" {
fetch = func(u string) (int, []byte, error) { return setupGateProbeFetchAccept(u, p.Accept) }
}
status, body, err := fetch(p.URL)
if err != nil {
return false, "", err
}