package integrations import ( "net/url" "strings" "testing" ) // R-1018: Nextcloud's OnlyOffice connector builds its server-to-server requests by APPENDING a path to the two inside // addresses the apply sets. The consequence pinned: the address the apply really sends, plus such a path, is a request // to the right container. Measured on demo-hp 2026-10-18: without the slash Nextcloud asked // http://onlyoffice:80cache/files/… and every save was lost. RED-PROOF: drop the slash from ncDocServerInternalURL → // the cache URL no longer parses (port "80cache") and this fails. func TestNextcloudApply_R1018_InternalAddressesTakeAPath(t *testing.T) { values := map[string]string{} for _, c := range nextcloudApplyCommands("https://office.example.hu", "secret") { if len(c.args) >= 11 && c.args[7] == "config:app:set" { values[c.args[9]] = strings.TrimPrefix(c.args[10], "--value=") } } for _, tc := range []struct { key, path, host string }{ {"DocumentServerInternalUrl", "cache/files/data/2153553391_5872/output.docx/output.docx", "onlyoffice:80"}, {"DocumentServerInternalUrl", "converter?shardkey=thumb_1", "onlyoffice:80"}, {"StorageUrl", "apps/onlyoffice/track?doc=x", "nextcloud"}, } { base, ok := values[tc.key] if !ok { t.Fatalf("the apply does not set %s (set: %v)", tc.key, values) } u, err := url.Parse(base + tc.path) if err != nil { t.Errorf("%s %q + %q is not a URL: %v", tc.key, base, tc.path, err) continue } if u.Host != tc.host || !strings.HasPrefix(u.Path, "/"+strings.SplitN(tc.path, "?", 2)[0][:4]) { t.Errorf("%s %q + %q reaches host %q path %q, want host %q", tc.key, base, tc.path, u.Host, u.Path, tc.host) } } if values["DocumentServerUrl"] != "https://office.example.hu" { t.Errorf("DocumentServerUrl = %q, want the public office address", values["DocumentServerUrl"]) } }