Skip to content

Commit aa3d26b

Browse files
ralyodioCodex Agent
andauthored
Normalize gig pagination params (#400)
Co-authored-by: Codex Agent <codex-agent@example.com>
1 parent e125e52 commit aa3d26b

2 files changed

Lines changed: 45 additions & 2 deletions

File tree

src/app/api/gigs/route.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,39 @@ describe("GET /api/gigs", () => {
144144
expect(json.pagination.totalPages).toBe(3);
145145
});
146146

147+
it("truncates fractional page and limit values before querying", async () => {
148+
const chain = chainResult({ data: null, error: null });
149+
chain.select = vi.fn().mockReturnValue(chain);
150+
chain.range = vi.fn().mockResolvedValue({ data: [], error: null, count: 30 });
151+
152+
mockFrom.mockReturnValue(chain);
153+
154+
const res = await GET(makeGetRequest({ page: "2.9", limit: "5.9" }));
155+
const json = await res.json();
156+
157+
expect(res.status).toBe(200);
158+
expect(chain.range).toHaveBeenCalledWith(5, 9);
159+
expect(json.pagination.page).toBe(2);
160+
expect(json.pagination.limit).toBe(5);
161+
expect(json.pagination.totalPages).toBe(6);
162+
});
163+
164+
it("defaults invalid and non-positive pagination values before querying", async () => {
165+
const chain = chainResult({ data: null, error: null });
166+
chain.select = vi.fn().mockReturnValue(chain);
167+
chain.range = vi.fn().mockResolvedValue({ data: [], error: null, count: 0 });
168+
169+
mockFrom.mockReturnValue(chain);
170+
171+
const res = await GET(makeGetRequest({ page: "-10", limit: "abc" }));
172+
const json = await res.json();
173+
174+
expect(res.status).toBe(200);
175+
expect(chain.range).toHaveBeenCalledWith(0, 19);
176+
expect(json.pagination.page).toBe(1);
177+
expect(json.pagination.limit).toBe(20);
178+
});
179+
147180
it("filters by listing_type when provided", async () => {
148181
const chain = chainResult({ data: null, error: null });
149182
chain.select = vi.fn().mockReturnValue(chain);

src/app/api/gigs/route.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ import { logActivity } from "@/lib/activity";
1010
const MAX_GIG_PAGE = 100_000;
1111
const MAX_GIG_LIMIT = 50;
1212

13+
function parsePositiveIntegerParam(
14+
value: string | null,
15+
defaultValue: number,
16+
max: number
17+
) {
18+
const parsed = Number(value && value.trim() !== "" ? value : defaultValue);
19+
const finiteValue = Number.isFinite(parsed) ? parsed : defaultValue;
20+
return Math.min(Math.max(1, Math.trunc(finiteValue)), max);
21+
}
22+
1323
// GET /api/gigs - List gigs (public)
1424
export async function GET(request: NextRequest) {
1525
try {
@@ -27,8 +37,8 @@ export async function GET(request: NextRequest) {
2737
account_type: searchParams.get("account_type") || undefined,
2838
listing_type: searchParams.get("listing_type") || undefined,
2939
sort: searchParams.get("sort") || "newest",
30-
page: Math.min(Number(searchParams.get("page")) || 1, MAX_GIG_PAGE),
31-
limit: Math.min(Number(searchParams.get("limit")) || 20, MAX_GIG_LIMIT),
40+
page: parsePositiveIntegerParam(searchParams.get("page"), 1, MAX_GIG_PAGE),
41+
limit: parsePositiveIntegerParam(searchParams.get("limit"), 20, MAX_GIG_LIMIT),
3242
});
3343

3444
if (!filters.success) {

0 commit comments

Comments
 (0)