• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

medplum / medplum / 31739184589
92%
main: 92%

Build:
Build:
LAST BUILD BRANCH: derrick-deflake-park-backlog-turns
DEFAULT BRANCH: main
Ran 13 Aug 2026 08:12PM UTC
Jobs 1
Files 880
Run time 2min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

13 Aug 2026 08:05PM UTC coverage: 92.184% (+0.003%) from 92.181%
31739184589

push

github

web-flow
perf(search): fix quadratic query string parsing on duplicate params (#10202)

* perf(search): fix quadratic query string parsing on duplicate params

parseQueryString() paired URLSearchParams.keys() with getAll(). keys() yields
one entry per name/value pair rather than per distinct name, so a query with n
copies of a param iterated n times and rescanned all n pairs on each iteration,
allocating a fresh n-element array and overwriting the same key each time.

This is on the hot path for every FHIR request, since the Express layer defers
query parsing to the router, and batch pays it three times per entry because
BatchProcessor calls router.find() during bucketing, identity resolution, and
execution.

Accumulate in a single pass instead. Output is unchanged: one occurrence stays a
bare string, repeats become an array in document order. Measured on 10k
duplicate params: 720ms -> 2.2ms.

Also:
- parseSearchRequest built its query array with push(...entries), which applies
  each entry as a separate argument and threw RangeError on very large queries.
- Hoist the five fixed special search parameter implementations in
  trySpecialSearchParameter so their FHIRPath expressions parse once at module
  load rather than per matching filter.
- Memoize deriveIdentifierSearchParameter and reuse parsed _include expressions
  via an LRU cache.

Signed-off-by: Derrick Farris <derrick@medplum.com>

* feat(fhir-router): reject query strings longer than 70,000 characters

Router.find() now rejects an over-length query string with a 400 before any
parsing work happens. The check is O(1) and runs at the single chokepoint shared
by ordinary requests and batch entries, which call find() directly.

Node caps the request line on real HTTP requests, so the vector this actually
bounds is URLs arriving inside a request body -- batch entry URLs in particular,
which are limited only by maxJsonSize. POST _search is unaffected: it reads the
form-encoded body, which Express already bo... (continued)

24007 of 27182 branches covered (88.32%)

Branch coverage included in aggregate %.

32 of 33 new or added lines in 6 files covered. (96.97%)

42328 of 44777 relevant lines covered (94.53%)

11903.63 hits per line

Uncovered Changes

Lines Coverage ∆ File
1
88.48
-0.41% packages/fhir-router/src/fhirrouter.ts
Jobs
ID Job ID Ran Files Coverage
1 31739184589.1 13 Aug 2026 08:12PM UTC 880
92.18
GitHub Action Run
Source Files on build 31739184589
  • Tree
  • List 880
  • Changed 7
  • Source Changed 6
  • Coverage Changed 7
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • Github Actions Build #31739184589
  • 25d8de21 on github
  • Prev Build on gh-readonly-queue/main/pr-10200-9aab4e2725146521d930a0776de07ecdd1462aff (#31731661234)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc