service: parse json job requests once

This commit is contained in:
Brad Stein 2026-03-31 20:53:59 -03:00
parent 1c9edb95f8
commit ecd31ffa1c
2 changed files with 36 additions and 10 deletions

View File

@ -95,7 +95,8 @@ func (a *App) handleBuild(w http.ResponseWriter, r *http.Request) {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed) http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return return
} }
node := requestValue(r, "node") values := requestValues(r)
node := values["node"]
job, err := a.Build(node) job, err := a.Build(node)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
@ -109,9 +110,10 @@ func (a *App) handleReplace(w http.ResponseWriter, r *http.Request) {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed) http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return return
} }
node := requestValue(r, "node") values := requestValues(r)
host := requestValue(r, "host") node := values["node"]
device := requestValue(r, "device") host := values["host"]
device := values["device"]
job, err := a.Replace(node, host, device) job, err := a.Replace(node, host, device)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
@ -204,19 +206,27 @@ func normalizeGroupValue(raw string) string {
return strings.TrimPrefix(value, "/") return strings.TrimPrefix(value, "/")
} }
func requestValue(r *http.Request, key string) string { func requestValues(r *http.Request) map[string]string {
values := map[string]string{}
if err := r.ParseForm(); err == nil { if err := r.ParseForm(); err == nil {
if value := strings.TrimSpace(r.Form.Get(key)); value != "" { for key, rawValues := range r.Form {
return value for _, raw := range rawValues {
if value := strings.TrimSpace(raw); value != "" {
values[key] = value
break
}
}
} }
} }
var payload map[string]any var payload map[string]any
if err := json.NewDecoder(r.Body).Decode(&payload); err == nil { if err := json.NewDecoder(r.Body).Decode(&payload); err == nil {
if value, ok := payload[key].(string); ok { for key, raw := range payload {
return strings.TrimSpace(value) if value, ok := raw.(string); ok && strings.TrimSpace(value) != "" {
values[key] = strings.TrimSpace(value)
}
} }
} }
return "" return values
} }
func writeJSON(w http.ResponseWriter, status int, payload any) { func writeJSON(w http.ResponseWriter, status int, payload any) {

View File

@ -121,6 +121,22 @@ func TestInternalSnapshotAndWatch(t *testing.T) {
} }
} }
func TestRequestValuesJSONBody(t *testing.T) {
req := httptest.NewRequest(http.MethodPost, "/api/jobs/replace", strings.NewReader(`{"node":"titan-13","host":"titan-20","device":"hosttmp:///tmp"}`))
req.Header.Set("Content-Type", "application/json")
values := requestValues(req)
if values["node"] != "titan-13" {
t.Fatalf("expected node titan-13, got %q", values["node"])
}
if values["host"] != "titan-20" {
t.Fatalf("expected host titan-20, got %q", values["host"])
}
if values["device"] != "hosttmp:///tmp" {
t.Fatalf("expected device hosttmp:///tmp, got %q", values["device"])
}
}
func newTestApp(t *testing.T) *App { func newTestApp(t *testing.T) *App {
t.Helper() t.Helper()
dir := t.TempDir() dir := t.TempDir()