From 56fe5749a5d6dc8b5c0914c67e0404032745578f Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Sun, 14 Jun 2026 09:48:08 +0200 Subject: [PATCH] F4+F6: 405 for non-POST /stacks/rescan; deploy POST reports 'started' not 'deployed' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- controller/internal/api/router.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/controller/internal/api/router.go b/controller/internal/api/router.go index dbf13a4..878fe12 100644 --- a/controller/internal/api/router.go +++ b/controller/internal/api/router.go @@ -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 {