Skip to content

fix: use one query validator in Express and Vercel search handlers (#97) - #370

Merged
Emmy123222 merged 1 commit into
Emmy123222:mainfrom
Hollujay:fix/shared-query-validator-97
Sep 3, 2026
Merged

fix: use one query validator in Express and Vercel search handlers (#97)#370
Emmy123222 merged 1 commit into
Emmy123222:mainfrom
Hollujay:fix/shared-query-validator-97

Conversation

@Hollujay

Copy link
Copy Markdown
Contributor

Summary

Closes #97.

server/index.ts had a local validateQuery() that capped query length at 256 chars and stripped null bytes / ASCII control characters (C0 + DEL). api/search.ts (the Vercel serverless equivalent) only did !q?.trim() and q.trim() — no length cap, no control-character stripping. That's a production-specific validation gap: a query that Express would reject with 400 (too long, or control-character-only) could sail straight through to Serper on Vercel.

Changes

  • src/lib/queryValidator.ts (new) — extracted validateQuery() / MAX_QUERY_LENGTH out of server/index.ts into a runtime-agnostic module (no Express or Vercel types), so both handlers call the exact same code.
  • server/index.ts — now imports validateQuery from src/lib/queryValidator.ts instead of defining it locally. /search, /images, /news behavior is unchanged.
  • api/search.ts — replaced the ad-hoc !q?.trim() / q.trim() checks with the shared validateQuery(), so it now enforces the same 256-char cap and control-character stripping as Express, and returns the same error strings.
  • src/lib/queryValidator.fixtures.ts (new) — one shared test table (valid queries, missing/empty/whitespace-only, over-length, control-character-only, control-chars-then-trim, unicode/punctuation) used by:
    • src/lib/queryValidator.test.ts (new) — unit tests against validateQuery() directly. Replaces server/validateQuery.test.ts (deleted; its coverage moved next to the code it tests).
    • server/payment.test.ts — new describe('shared query-validator table — /search (Express)') block that drives the same table through the real Express route via supertest.
    • api/search.test.ts — new describe('shared query-validator table — /api/search (Vercel)') block that drives the same table through the real Vercel handler.
      Both integration blocks assert identical status codes and identical cleaned queries for every case in the table — this is the "shared test table" the issue's acceptance criteria asked for.
  • vite.config.ts — added a 100% coverage ratchet for the new src/lib/queryValidator.ts, and adjusted server/index.ts's function/branch ratchet down slightly (55%→50%, 60%→55%) since the validator logic — and the branches/tests that exercised it — moved out of that file into the shared module.

x402 payment logic (header parsing, replay protection, settlement amounts) is untouched on both runtimes — only the pre-payment query-validation gate changed.

Test plan

  • npm run typecheck:all passes (frontend, server, api, mcp, scripts)
  • npm run lint passes (eslint . --max-warnings=0)
  • npx vitest run — all 224 tests pass across 16 test files, including the new shared-table suites in src/lib/queryValidator.test.ts, server/payment.test.ts, and api/search.test.ts
  • npm run test:coverage:check — passes with updated ratchets
  • npm run build — production build succeeds
  • N/A screenshots — backend validation change, no UI impact

@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

@Hollujay is attempting to deploy a commit to the Emmanuel's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@Hollujay Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Hollujay
Hollujay force-pushed the fix/shared-query-validator-97 branch from 4003dc8 to 5700124 Compare September 1, 2026 13:30
…lers

server/index.ts stripped control characters and capped query length via
a local validateQuery(); api/search.ts only trimmed whitespace, so a
control-character or over-length query could 400 on Express but sail
through to Serper on Vercel — a production-specific validation gap.

- Extract validateQuery/MAX_QUERY_LENGTH into src/lib/queryValidator.ts,
  a runtime-agnostic module imported by both server/index.ts and
  api/search.ts.
- Add src/lib/queryValidator.fixtures.ts: a single shared test table,
  consumed by src/lib/queryValidator.test.ts (unit), and by
  server/payment.test.ts + api/search.test.ts (integration) to assert
  both handlers return identical status codes and cleaned queries for
  the same input.
- Move server/validateQuery.test.ts's unit coverage into
  src/lib/queryValidator.test.ts alongside the code it tests.
- Update vite.config.ts coverage ratchets: add a 100% threshold for the
  new src/lib/queryValidator.ts, and adjust server/index.ts's
  function/branch ratchet to reflect the validator logic moving out.

Closes Emmy123222#97
@Hollujay
Hollujay force-pushed the fix/shared-query-validator-97 branch from 5f4858d to 9b38c3d Compare September 2, 2026 12:51
@Emmy123222
Emmy123222 merged commit 453630e into Emmy123222:main Sep 3, 2026
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use one query validator in Express and Vercel search handlers

2 participants