From 4bf3fd7c4239fe5832ea7c2bc9c912283af0573a Mon Sep 17 00:00:00 2001 From: wbtiger <28288271@qq.com> Date: Sat, 4 Apr 2026 14:04:14 +0800 Subject: [PATCH] feat(items): add pagination with page/limit query params - Support page and limit query parameters - Default limit: 20, max: 100 - Return X-Total-Count header with total item count - Sort items by ID for stable pagination Closes #1 --- .devharness/operations.db | Bin 0 -> 12288 bytes handlers/items.go | 41 ++++++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 .devharness/operations.db diff --git a/.devharness/operations.db b/.devharness/operations.db new file mode 100644 index 0000000000000000000000000000000000000000..e9f76f54aae29802dbd02e757bbd34f512ecd07d GIT binary patch literal 12288 zcmeI#O-sWt7zgllin_sGZeFv~6hx5u0jyh;VK--&fjgDBMyYIVZBx*zc$}ZgFC};} zscdDZ;dT5UNSowo9-3c!$>`1rl%$VQG8c-rNrPAxxuBE~V(GS{+cL~}cRA2^Gu{*y zIsN>p*1t)qwji}d{cF<#ayRskd0tJU_VQ zbTD=tlT4LRS^BqrElIoV${stMwqhCjLHN`%kH;br^VEAzqcE>!<`S7^GqpZ9O{7rL z_w?bKcJ-U{UZ1ThcE+yD2HZ1~BX0MHrb-t3|5#BeAGb?;hu2Mu1fefq)0de(&wCUDo`;S!})((KQHzL Y0SG_<0uX=z1Rwwb2tWV=5Xc370c~A)F8}}l literal 0 HcmV?d00001 diff --git a/handlers/items.go b/handlers/items.go index 16c0f49..3238bac 100644 --- a/handlers/items.go +++ b/handlers/items.go @@ -2,7 +2,10 @@ package handlers import ( "encoding/json" + "fmt" "net/http" + "sort" + "strconv" "sync" ) @@ -19,20 +22,50 @@ var ( storeMu sync.RWMutex ) -// GetItems returns all items. +// GetItems returns items with pagination support. +// Query params: page (default 1), limit (default 20, max 100). +// Response header: X-Total-Count with total item count. func GetItems(w http.ResponseWriter, r *http.Request) { storeMu.RLock() defer storeMu.RUnlock() - // BUG: when store is nil (fresh start), json.Marshal(nil map values) - // causes unexpected behavior — should return [] but may panic or 500. + // Parse pagination params + page, _ := strconv.Atoi(r.URL.Query().Get("page")) + if page < 1 { + page = 1 + } + limit, _ := strconv.Atoi(r.URL.Query().Get("limit")) + if limit < 1 { + limit = 20 + } + if limit > 100 { + limit = 100 + } + + // Collect and sort items for stable pagination items := make([]Item, 0, len(store)) for _, item := range store { items = append(items, item) } + sort.Slice(items, func(i, j int) bool { + return items[i].ID < items[j].ID + }) + + // Apply pagination + total := len(items) + start := (page - 1) * limit + if start > total { + start = total + } + end := start + limit + if end > total { + end = total + } + paged := items[start:end] w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(items); err != nil { + w.Header().Set("X-Total-Count", fmt.Sprintf("%d", total)) + if err := json.NewEncoder(w).Encode(paged); err != nil { http.Error(w, `{"error":"internal server error"}`, http.StatusInternalServerError) } }