fix(landscape): accept an empty run body; pin the builder's Alpine release
POST /landscape/runs documents an optional body, but DecodeJSON returned io.EOF on an empty one and the handler turned that into 400 — breaking the most common call, an all-defaults run. decodeRunRequest now treats io.EOF as the zero request; a malformed body is still 400. The Dockerfile's Alpine ABI coupling was enforced only by a comment: a floating golang:1.26-alpine builder against a pinned alpine:3.24 runtime would build green and die at startup on a libgdal soname mismatch as soon as the Go image rolls forward. Both stages are now pinned to 3.24. Also: the route-mount test walks the router so all six routes are asserted (GET /slots and GET /results included), and the spec documents the 404 those two return when migration 00011's seeded groups are absent. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"gis/internal/landscape"
|
||||
@@ -89,12 +91,26 @@ func (h *LandscapeHandler) uploadSlot(w http.ResponseWriter, r *http.Request) {
|
||||
httputil.WriteJSON(w, http.StatusCreated, dataset)
|
||||
}
|
||||
|
||||
// decodeRunRequest reads the run body. The whole body is optional — every field
|
||||
// has a default — so an empty body is the zero request (a default incremental
|
||||
// run), not an error. A malformed body writes a 400 and reports false.
|
||||
func decodeRunRequest(w http.ResponseWriter, r *http.Request) (runRequest, bool) {
|
||||
req, err := httputil.DecodeJSON[runRequest](w, r)
|
||||
switch {
|
||||
case errors.Is(err, io.EOF):
|
||||
return runRequest{}, true
|
||||
case err != nil:
|
||||
httputil.WriteError(w, http.StatusBadRequest, "invalid request body")
|
||||
return runRequest{}, false
|
||||
}
|
||||
return req, true
|
||||
}
|
||||
|
||||
// createRun queues a Landscape Program run and returns it with 202 Accepted;
|
||||
// the worker executes it asynchronously.
|
||||
func (h *LandscapeHandler) createRun(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := httputil.DecodeJSON[runRequest](w, r)
|
||||
if err != nil {
|
||||
httputil.WriteError(w, http.StatusBadRequest, "invalid request body")
|
||||
req, ok := decodeRunRequest(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if err := h.validate.Struct(req); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user