fix: prevent root wildcard static routes from overriding mount routes#1686
Closed
raunak-rpm wants to merge 2 commits intoelysiajs:mainfrom
Closed
fix: prevent root wildcard static routes from overriding mount routes#1686raunak-rpm wants to merge 2 commits intoelysiajs:mainfrom
raunak-rpm wants to merge 2 commits intoelysiajs:mainfrom
Conversation
…elysiajs#1515) When using static Response/HTMLBundle on root wildcard routes (e.g., GET /*), Bun's nativeStaticResponse optimization would add them to Bun's static route table, which has highest priority and bypasses Elysia's dynamic router. This caused SPA fallback patterns with mounted APIs to fail: app.mount('/api', backend) .get('/*', staticHtmlResponse) The /api/* routes would return HTML instead of API responses because the /* wildcard in Bun's static table matched everything. Solution: - During listen(), collect mount prefixes by scanning router.history for routes with hooks.config.mount flag - In createStaticRoute(), skip root wildcard paths (/* or /) when mounts exist - This forces root wildcards through the dynamic router where the route specificity fix from elysiajs#1682 correctly handles priority Production-grade approach: - Minimal performance impact: only scans during .listen() once - Surgical fix: only affects root wildcards when mounts exist - Preserves optimization: specific static routes still go to Bun table - Backwards compatible: doesn't break existing apps without mounts Fixes elysiajs#1515
Contributor
WalkthroughThe PR updates the Bun adapter to record mounted route prefixes at startup and prevents root-level wildcard static routes from being registered when mounts exist, so mounted routes are not shadowed by generic wildcard static handlers. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Also update tests to use actual fetch() instead of .handle() since the fix targets Bun's static route table optimization.
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes issue #1515 - Cannot implement SPA fallback routing with mounted APIs
When using static
Response/HTMLBundleon root wildcard routes (e.g.,GET /*), Bun'snativeStaticResponseoptimization would bypass Elysia's dynamic router, causing mounted API routes to return HTML instead of JSON.This PR requires PR #1685 to be merged first. PR #1685 fixes route specificity in the dynamic router (
compose.ts), which is necessary for this fix to work properly. Without #1685, requests would still be incorrectly routed even after bypassing Bun's static table.Root Cause
Static responses are added directly to Bun's static route table, which has highest priority and bypasses Elysia's dynamic router entirely. A root wildcard in the static table matches everything including mount routes.
Solution
Modified:
src/adapter/bun/index.tslisten(), collect mount prefixes by scanningrouter.historyfor routes withhooks.config.mountflagcreateStaticRoute(), skip root wildcard paths (/*,/*/,/, ``) when mounts existWhy This Approach
.listen(), not per-requestTest Coverage
Added comprehensive tests in
test/core/spa-fallback.test.tscovering:/public/*) still workAll tests pass with PR #1685 merged.
Verification
Fixes #1515
Depends on: #1685
Summary by CodeRabbit
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.