F4+F6: 405 for non-POST /stacks/rescan; deploy POST reports 'started' not 'deployed'

F4: GET /api/stacks/rescan fell through to GET /stacks/{name} → misleading
'stack not found: rescan'. Now returns 405 + Allow: POST.
F6: the deploy POST returns before compose/health complete (async; UI polls).
Message changed 'Stack X deployed' → 'Telepítés elindítva…' and status 200→202
Accepted, so API/script consumers aren't told a deploy finished when it hasn't.
UI checks data.ok (not HTTP status), so 202 is safe.
This commit is contained in:
2026-06-14 09:48:08 +02:00
parent 2cf3fadaec
commit 56fe5749a5
+12 -2
View File
@@ -112,6 +112,12 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
case path == "/stacks/rescan" && req.Method == http.MethodPost:
r.rescanStacks(w, req)
// F4: /api/stacks/rescan with a non-POST method must be a clear 405, not fall through to the
// GET /stacks/{name} lookup below (which returned the misleading "stack not found: rescan").
case path == "/stacks/rescan":
w.Header().Set("Allow", http.MethodPost)
writeJSON(w, http.StatusMethodNotAllowed, apiResponse{OK: false, Error: "method not allowed: use POST /api/stacks/rescan"})
// GET /api/stacks/{name}
case strings.HasPrefix(path, "/stacks/") && req.Method == http.MethodGet && !hasSubpath(path, "/stacks/"):
r.getStack(w, req, trimSegment(path, "/stacks/"))
@@ -378,11 +384,15 @@ func (r *Router) deployStack(w http.ResponseWriter, req *http.Request, name stri
return
}
resp := apiResponse{OK: true, Message: "Stack " + name + " deployed"}
// F6: the deploy runs asynchronously (compose pull/up + health happen after this returns; the UI
// polls GET /api/stacks/{name}). The old "Stack X deployed" message asserted completion before it
// was true — misleading for API/script consumers. Report that the deploy STARTED, not that it
// finished. 202 Accepted reflects "accepted, processing"; ok:true is preserved for the UI.
resp := apiResponse{OK: true, Message: "Telepítés elindítva az állapot a kártyán követhető"}
if warning != "" {
resp.Data = map[string]string{"warning": warning}
}
writeJSON(w, http.StatusOK, resp)
writeJSON(w, http.StatusAccepted, resp)
// Push app deployed event to Hub
if r.notifier != nil {