Compare commits

..

1 Commits

Author SHA1 Message Date
Hein
b157379ff8 fix(restheadspec): return 200 OK with empty body instead of 204 on zero results
Frontend clients are sensitive to 204 No Content responses; always return 200
with an empty array/object and rely on X-No-Data-Found header to signal absence
of records.

Also treat "change" as an alias for "update" in recursive CUD processing.
2026-05-19 08:56:11 +02:00
3 changed files with 13 additions and 17 deletions

View File

@@ -141,7 +141,7 @@ func (p *NestedCUDProcessor) ProcessNestedCUD(
logger.Debug("Skipping insert for %s - no data columns besides _request", tableName) logger.Debug("Skipping insert for %s - no data columns besides _request", tableName)
} }
case "update": case "update", "change":
// Only perform update if we have data to update // Only perform update if we have data to update
if hasData { if hasData {
rows, err := p.processUpdate(ctx, regularData, tableName, data[pkName]) rows, err := p.processUpdate(ctx, regularData, tableName, data[pkName])

View File

@@ -14,23 +14,23 @@ func TestNormalizeResultArray_EmptyArrayWhenNoID(t *testing.T) {
handler := &Handler{} handler := &Handler{}
tests := []struct { tests := []struct {
name string name string
input interface{} input interface{}
shouldBeEmptyObj bool shouldBeEmptyObj bool
}{ }{
{ {
name: "nil should return empty object", name: "nil should return empty object",
input: nil, input: nil,
shouldBeEmptyObj: true, shouldBeEmptyObj: true,
}, },
{ {
name: "empty slice should return empty object", name: "empty slice should return empty object",
input: []*EmptyTestModel{}, input: []*EmptyTestModel{},
shouldBeEmptyObj: true, shouldBeEmptyObj: true,
}, },
{ {
name: "single element should return the element", name: "single element should return the element",
input: []*EmptyTestModel{{ID: 1, Name: "test"}}, input: []*EmptyTestModel{{ID: 1, Name: "test"}},
shouldBeEmptyObj: false, shouldBeEmptyObj: false,
}, },
{ {
@@ -138,9 +138,9 @@ func TestSendResponseWithOptions_NoDataFoundHeader(t *testing.T) {
t.Errorf("Expected X-No-Data-Found header to be 'true', got '%s'", mockWriter.headers["X-No-Data-Found"]) t.Errorf("Expected X-No-Data-Found header to be 'true', got '%s'", mockWriter.headers["X-No-Data-Found"])
} }
// Check status code is 204 when no records found // Check status code is 200 even when no records found
if mockWriter.statusCode != 204 { if mockWriter.statusCode != 200 {
t.Errorf("Expected status code 204, got %d", mockWriter.statusCode) t.Errorf("Expected status code 200, got %d", mockWriter.statusCode)
} }
// Verify the body is an empty array (list request, SingleRecordAsObject not set) // Verify the body is an empty array (list request, SingleRecordAsObject not set)

View File

@@ -2507,11 +2507,7 @@ func (h *Handler) sendResponseWithOptions(w common.ResponseWriter, data interfac
data = h.normalizeResultArray(data) data = h.normalizeResultArray(data)
} }
if dataLen == 0 { w.WriteHeader(http.StatusOK)
w.WriteHeader(http.StatusNoContent)
} else {
w.WriteHeader(http.StatusOK)
}
if err := w.WriteJSON(data); err != nil { if err := w.WriteJSON(data); err != nil {
logger.Error("Failed to write JSON response: %v", err) logger.Error("Failed to write JSON response: %v", err)