Skip to content

Commit f7fa003

Browse files
authored
fix(xref): move 1000-cap inside filter() and tighten route validation
- filter(): apply .slice(0, 1000) on the empty-term browse result before returning so the MemCache stores a bounded list (not the full unbounded DataEntry[]), fixing the memory safety concern - searchOne(): remove the duplicate post-cache slice(0,1000) guards that were the only cap, now redundant since filter() is already bounded - search.get.ts: remove !types?.length from the 400-guard so that ?type=... without specs or term returns a proper 400 instead of silently falling through to an empty-string term search that returns misleading results; update error message accordingly Agent-Logs-Url: https://github.com/speced/respec-web-services/sessions/eafb7347-faf9-4e79-a820-4546c4b7b010
1 parent bc5238e commit f7fa003

2 files changed

Lines changed: 4 additions & 5 deletions

File tree

routes/xref/lib/search.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,7 @@ export function searchOne(
9898
const filtered = cache.getOr(query.id, () => filter(query, store, options));
9999

100100
let prefereredData = filterBySpecType(filtered, options.spec_type);
101-
if (!query.term) prefereredData = prefereredData.slice(0, 1000);
102101
prefereredData = filterPreferLatestVersion(prefereredData);
103-
if (!query.term) prefereredData = prefereredData.slice(0, 1000);
104102
const result = prefereredData.map(item => pickFields(item, options.fields));
105103
return result;
106104
}
@@ -123,11 +121,12 @@ function normalizeQuery(query: Query, options: Options) {
123121

124122
function filter(query: Query, store: Store, options: Options) {
125123
// When no term is provided but specs are, return all entries from those specs.
124+
// Cap at 1000 here so the cached value is memory-bounded.
126125
if (!query.term && query.specs?.length) {
127126
const entries = collectBySpecs(query.specs, store);
128127
const byType = filterByType(entries, query);
129128
const byForContext = filterByForContext(byType, query, options);
130-
return byForContext;
129+
return byForContext.slice(0, 1000);
131130
}
132131

133132
let result: DataEntry[] = [];

routes/xref/search.get.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ export default async function route(req: IRequest, res: Response) {
1717
const { term, for: forContext } = req.query;
1818
const specs = splitQueryParam(req.query.specs);
1919
const types = splitQueryParam(req.query.type)?.flat(2) as Query["types"];
20-
if (typeof term === "undefined" && !specs?.length && !types?.length) {
20+
if (typeof term === "undefined" && !specs?.length) {
2121
res.status(400).json({
22-
message: { type: "error", text: "Missing required query parameter: term (or provide specs or type)" },
22+
message: { type: "error", text: "Missing required query parameter: term (or provide specs)" },
2323
});
2424
return;
2525
}

0 commit comments

Comments
 (0)