fix: use explicit conditional calls and validate negative params
This commit is contained in:
@@ -21,7 +21,7 @@ export async function ebayRoute(req: Request): Promise<Response> {
|
|||||||
|
|
||||||
const minPriceParam = reqUrl.searchParams.get("minPrice");
|
const minPriceParam = reqUrl.searchParams.get("minPrice");
|
||||||
const minPrice = minPriceParam ? parseInt(minPriceParam, 10) : undefined;
|
const minPrice = minPriceParam ? parseInt(minPriceParam, 10) : undefined;
|
||||||
if (minPriceParam && Number.isNaN(minPrice)) {
|
if (minPriceParam && (Number.isNaN(minPrice) || minPrice < 0)) {
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{ message: "Invalid minPrice parameter" },
|
{ message: "Invalid minPrice parameter" },
|
||||||
{ status: 400 },
|
{ status: 400 },
|
||||||
@@ -29,7 +29,7 @@ export async function ebayRoute(req: Request): Promise<Response> {
|
|||||||
}
|
}
|
||||||
const maxPriceParam = reqUrl.searchParams.get("maxPrice");
|
const maxPriceParam = reqUrl.searchParams.get("maxPrice");
|
||||||
const maxPrice = maxPriceParam ? parseInt(maxPriceParam, 10) : undefined;
|
const maxPrice = maxPriceParam ? parseInt(maxPriceParam, 10) : undefined;
|
||||||
if (maxPriceParam && Number.isNaN(maxPrice)) {
|
if (maxPriceParam && (Number.isNaN(maxPrice) || maxPrice < 0)) {
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{ message: "Invalid maxPrice parameter" },
|
{ message: "Invalid maxPrice parameter" },
|
||||||
{ status: 400 },
|
{ status: 400 },
|
||||||
@@ -49,7 +49,7 @@ export async function ebayRoute(req: Request): Promise<Response> {
|
|||||||
|
|
||||||
const maxItemsParam = reqUrl.searchParams.get("maxItems");
|
const maxItemsParam = reqUrl.searchParams.get("maxItems");
|
||||||
const maxItems = maxItemsParam ? parseInt(maxItemsParam, 10) : undefined;
|
const maxItems = maxItemsParam ? parseInt(maxItemsParam, 10) : undefined;
|
||||||
if (maxItemsParam && Number.isNaN(maxItems)) {
|
if (maxItemsParam && (Number.isNaN(maxItems) || maxItems < 0)) {
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{ message: "Invalid maxItems parameter" },
|
{ message: "Invalid maxItems parameter" },
|
||||||
{ status: 400 },
|
{ status: 400 },
|
||||||
@@ -66,12 +66,11 @@ export async function ebayRoute(req: Request): Promise<Response> {
|
|||||||
buyItNowOnly,
|
buyItNowOnly,
|
||||||
canadaOnly,
|
canadaOnly,
|
||||||
};
|
};
|
||||||
const items = await fetchEbayItems(
|
const items = hideUnstableResults
|
||||||
SEARCH_QUERY,
|
? await fetchEbayItems(SEARCH_QUERY, 1, opts, {
|
||||||
1,
|
hideUnstableResults: true,
|
||||||
opts,
|
})
|
||||||
...(hideUnstableResults ? [{ hideUnstableResults: true }] : []),
|
: await fetchEbayItems(SEARCH_QUERY, 1, opts);
|
||||||
);
|
|
||||||
|
|
||||||
const isEmpty = hideUnstableResults
|
const isEmpty = hideUnstableResults
|
||||||
? items.results.length === 0 && items.unstableResults.length === 0
|
? items.results.length === 0 && items.unstableResults.length === 0
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export async function facebookRoute(req: Request): Promise<Response> {
|
|||||||
const LOCATION = reqUrl.searchParams.get("location") || "toronto";
|
const LOCATION = reqUrl.searchParams.get("location") || "toronto";
|
||||||
const maxItemsParam = reqUrl.searchParams.get("maxItems");
|
const maxItemsParam = reqUrl.searchParams.get("maxItems");
|
||||||
const maxItems = maxItemsParam ? parseInt(maxItemsParam, 10) : 25;
|
const maxItems = maxItemsParam ? parseInt(maxItemsParam, 10) : 25;
|
||||||
if (maxItemsParam && Number.isNaN(maxItems)) {
|
if (maxItemsParam && (Number.isNaN(maxItems) || maxItems < 0)) {
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{ message: "Invalid maxItems parameter" },
|
{ message: "Invalid maxItems parameter" },
|
||||||
{ status: 400 },
|
{ status: 400 },
|
||||||
@@ -30,13 +30,11 @@ export async function facebookRoute(req: Request): Promise<Response> {
|
|||||||
reqUrl.searchParams.get("unstableFilter") === "true";
|
reqUrl.searchParams.get("unstableFilter") === "true";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const items = await fetchFacebookItems(
|
const items = hideUnstableResults
|
||||||
SEARCH_QUERY,
|
? await fetchFacebookItems(SEARCH_QUERY, 1, LOCATION, maxItems, {
|
||||||
1,
|
hideUnstableResults: true,
|
||||||
LOCATION,
|
})
|
||||||
maxItems,
|
: await fetchFacebookItems(SEARCH_QUERY, 1, LOCATION, maxItems);
|
||||||
...(hideUnstableResults ? [{ hideUnstableResults: true }] : []),
|
|
||||||
);
|
|
||||||
|
|
||||||
const isEmpty = hideUnstableResults
|
const isEmpty = hideUnstableResults
|
||||||
? items.results.length === 0 && items.unstableResults.length === 0
|
? items.results.length === 0 && items.unstableResults.length === 0
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export async function kijijiRoute(req: Request): Promise<Response> {
|
|||||||
|
|
||||||
const maxPagesParam = reqUrl.searchParams.get("maxPages");
|
const maxPagesParam = reqUrl.searchParams.get("maxPages");
|
||||||
const maxPages = maxPagesParam ? parseInt(maxPagesParam, 10) : 5;
|
const maxPages = maxPagesParam ? parseInt(maxPagesParam, 10) : 5;
|
||||||
if (maxPagesParam && Number.isNaN(maxPages)) {
|
if (maxPagesParam && (Number.isNaN(maxPages) || maxPages < 0)) {
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{ message: "Invalid maxPages parameter" },
|
{ message: "Invalid maxPages parameter" },
|
||||||
{ status: 400 },
|
{ status: 400 },
|
||||||
@@ -27,7 +27,7 @@ export async function kijijiRoute(req: Request): Promise<Response> {
|
|||||||
}
|
}
|
||||||
const priceMinParam = reqUrl.searchParams.get("priceMin");
|
const priceMinParam = reqUrl.searchParams.get("priceMin");
|
||||||
const priceMin = priceMinParam ? parseInt(priceMinParam, 10) : undefined;
|
const priceMin = priceMinParam ? parseInt(priceMinParam, 10) : undefined;
|
||||||
if (priceMinParam && Number.isNaN(priceMin)) {
|
if (priceMinParam && (Number.isNaN(priceMin) || priceMin < 0)) {
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{ message: "Invalid priceMin parameter" },
|
{ message: "Invalid priceMin parameter" },
|
||||||
{ status: 400 },
|
{ status: 400 },
|
||||||
@@ -35,7 +35,7 @@ export async function kijijiRoute(req: Request): Promise<Response> {
|
|||||||
}
|
}
|
||||||
const priceMaxParam = reqUrl.searchParams.get("priceMax");
|
const priceMaxParam = reqUrl.searchParams.get("priceMax");
|
||||||
const priceMax = priceMaxParam ? parseInt(priceMaxParam, 10) : undefined;
|
const priceMax = priceMaxParam ? parseInt(priceMaxParam, 10) : undefined;
|
||||||
if (priceMaxParam && Number.isNaN(priceMax)) {
|
if (priceMaxParam && (Number.isNaN(priceMax) || priceMax < 0)) {
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{ message: "Invalid priceMax parameter" },
|
{ message: "Invalid priceMax parameter" },
|
||||||
{ status: 400 },
|
{ status: 400 },
|
||||||
@@ -65,14 +65,22 @@ export async function kijijiRoute(req: Request): Promise<Response> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const items = await fetchKijijiItems(
|
const items = hideUnstableResults
|
||||||
SEARCH_QUERY,
|
? await fetchKijijiItems(
|
||||||
4, // 4 requests per second for faster scraping
|
SEARCH_QUERY,
|
||||||
"https://www.kijiji.ca",
|
4, // 4 requests per second for faster scraping
|
||||||
searchOptions,
|
"https://www.kijiji.ca",
|
||||||
{},
|
searchOptions,
|
||||||
...(hideUnstableResults ? [{ hideUnstableResults: true }] : []),
|
{},
|
||||||
);
|
{ hideUnstableResults: true },
|
||||||
|
)
|
||||||
|
: await fetchKijijiItems(
|
||||||
|
SEARCH_QUERY,
|
||||||
|
4, // 4 requests per second for faster scraping
|
||||||
|
"https://www.kijiji.ca",
|
||||||
|
searchOptions,
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
const isEmpty = hideUnstableResults
|
const isEmpty = hideUnstableResults
|
||||||
? items.results.length === 0 && items.unstableResults.length === 0
|
? items.results.length === 0 && items.unstableResults.length === 0
|
||||||
|
|||||||
@@ -540,4 +540,102 @@ describe("API routes", () => {
|
|||||||
const body = await response.json();
|
const body = await response.json();
|
||||||
expect(body.message).toBe("Invalid priceMax parameter");
|
expect(body.message).toBe("Invalid priceMax parameter");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("facebookRoute returns 400 for negative maxItems", async () => {
|
||||||
|
const { facebookRoute } = await import("../src/routes/facebook");
|
||||||
|
|
||||||
|
const response = await facebookRoute(
|
||||||
|
new Request(
|
||||||
|
"http://localhost/api/facebook?q=laptop&maxItems=-1",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(response.status).toBe(400);
|
||||||
|
const body = await response.json();
|
||||||
|
expect(body.message).toBe("Invalid maxItems parameter");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ebayRoute returns 400 for negative maxItems", async () => {
|
||||||
|
const { ebayRoute } = await import("../src/routes/ebay");
|
||||||
|
|
||||||
|
const response = await ebayRoute(
|
||||||
|
new Request(
|
||||||
|
"http://localhost/api/ebay?q=laptop&maxItems=-1",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(response.status).toBe(400);
|
||||||
|
const body = await response.json();
|
||||||
|
expect(body.message).toBe("Invalid maxItems parameter");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ebayRoute returns 400 for negative minPrice", async () => {
|
||||||
|
const { ebayRoute } = await import("../src/routes/ebay");
|
||||||
|
|
||||||
|
const response = await ebayRoute(
|
||||||
|
new Request(
|
||||||
|
"http://localhost/api/ebay?q=laptop&minPrice=-5",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(response.status).toBe(400);
|
||||||
|
const body = await response.json();
|
||||||
|
expect(body.message).toBe("Invalid minPrice parameter");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ebayRoute returns 400 for negative maxPrice", async () => {
|
||||||
|
const { ebayRoute } = await import("../src/routes/ebay");
|
||||||
|
|
||||||
|
const response = await ebayRoute(
|
||||||
|
new Request(
|
||||||
|
"http://localhost/api/ebay?q=laptop&maxPrice=-10",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(response.status).toBe(400);
|
||||||
|
const body = await response.json();
|
||||||
|
expect(body.message).toBe("Invalid maxPrice parameter");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("kijijiRoute returns 400 for negative maxPages", async () => {
|
||||||
|
const { kijijiRoute } = await import("../src/routes/kijiji");
|
||||||
|
|
||||||
|
const response = await kijijiRoute(
|
||||||
|
new Request(
|
||||||
|
"http://localhost/api/kijiji?q=laptop&maxPages=-2",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(response.status).toBe(400);
|
||||||
|
const body = await response.json();
|
||||||
|
expect(body.message).toBe("Invalid maxPages parameter");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("kijijiRoute returns 400 for negative priceMin", async () => {
|
||||||
|
const { kijijiRoute } = await import("../src/routes/kijiji");
|
||||||
|
|
||||||
|
const response = await kijijiRoute(
|
||||||
|
new Request(
|
||||||
|
"http://localhost/api/kijiji?q=laptop&priceMin=-5",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(response.status).toBe(400);
|
||||||
|
const body = await response.json();
|
||||||
|
expect(body.message).toBe("Invalid priceMin parameter");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("kijijiRoute returns 400 for negative priceMax", async () => {
|
||||||
|
const { kijijiRoute } = await import("../src/routes/kijiji");
|
||||||
|
|
||||||
|
const response = await kijijiRoute(
|
||||||
|
new Request(
|
||||||
|
"http://localhost/api/kijiji?q=laptop&priceMax=-10",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(response.status).toBe(400);
|
||||||
|
const body = await response.json();
|
||||||
|
expect(body.message).toBe("Invalid priceMax parameter");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user