From a5558502479f00bdbd6f7314a99d5cce09624542 Mon Sep 17 00:00:00 2001 From: saltyaom Date: Wed, 14 Jan 2026 10:56:47 +0700 Subject: [PATCH] :wrench: fix: #1671 mount produce incorrect url --- CHANGELOG.md | 1 + example/a.ts | 17 ++++++++++++++++- src/adapter/bun/compose.ts | 2 +- src/index.ts | 6 +++++- src/utils.ts | 10 +++++++--- test/core/mount.test.ts | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 63 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d680bb14..113c3466 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # 1.4.22 Bug fix: +- [#1671](https://github.com/elysiajs/elysia/issues/1671) mount() produces incorrect URL path when Elysia instance has prefix option - ValueError with summary missing types - Elysia not using Bun.routes diff --git a/example/a.ts b/example/a.ts index c19a2462..bac7371a 100644 --- a/example/a.ts +++ b/example/a.ts @@ -1,3 +1,18 @@ import { Elysia } from '../src' -const app = new Elysia().get('/', () => 'a').listen(3000) +const sdkApp = new Elysia({ prefix: '/sdk' }).mount( + '/problems-domain', + (request) => { + console.log(request.url) + + return Response.json({ path: new URL(request.url).pathname }) + } +) + +const app = new Elysia().use(sdkApp) + +const response = await app + .handle(new Request('http://localhost/sdk/problems-domain/problems')) + .then((x) => x.text()) + +console.log(response) diff --git a/src/adapter/bun/compose.ts b/src/adapter/bun/compose.ts index b0b05915..1f30e8cf 100644 --- a/src/adapter/bun/compose.ts +++ b/src/adapter/bun/compose.ts @@ -33,7 +33,7 @@ const createContext = ( const getQi = `const u=request.url,` + `s=u.indexOf('/',${standardHostname ? 11 : 7}),` + - `qi=u.indexOf('?', s + 1)\n` + `qi=u.indexOf('?',s+1)\n` const needsQuery = inference.query || diff --git a/src/index.ts b/src/index.ts index de83bb87..c9c011be 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5613,8 +5613,12 @@ export default class Elysia< throw new Error('Invalid handler') })() - const length = path.length - (path.endsWith('*') ? 1 : 0) + const fullPath = + typeof path === 'string' && this.config.prefix + ? this.config.prefix + path + : path + const length = fullPath.length - (path.endsWith('*') ? 1 : 0) const handler: Handler = ({ request, path }) => handle( new Request( diff --git a/src/utils.ts b/src/utils.ts index 761c167b..18fffdea 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -28,9 +28,13 @@ import { ElysiaFile } from './universal/file' export const hasHeaderShorthand = 'toJSON' in new Headers() export const replaceUrlPath = (url: string, pathname: string) => { - const urlObject = new URL(url) - urlObject.pathname = pathname - return urlObject.toString() + const pathStartIndex = url.indexOf('/', 11) + const queryIndex = url.indexOf('?', pathStartIndex) + + if (queryIndex === -1) + return `${url.slice(0, pathStartIndex)}${pathname.charCodeAt(0) === 47 ? '' : '/'}${pathname}` + + return `${url.slice(0, pathStartIndex)}${pathname.charCodeAt(0) === 47 ? '' : '/'}${pathname}${url.slice(queryIndex)}` } export const isClass = (v: Object) => diff --git a/test/core/mount.test.ts b/test/core/mount.test.ts index 0f44df44..ff17b5b1 100644 --- a/test/core/mount.test.ts +++ b/test/core/mount.test.ts @@ -137,4 +137,37 @@ describe('Mount', () => { 'x-test': 'test' }) }) + + it('mount without prefix - strips mount path', async () => { + const app = new Elysia().mount('/sdk/problems-domain', (request) => { + return Response.json({ path: new URL(request.url).pathname }) + }) + + const response = await app + .handle( + new Request('http://localhost/sdk/problems-domain/problems') + ) + .then((x) => x.json() as Promise<{ path: string }>) + + expect(response.path).toBe('/problems') + }) + + it('mount with prefix - should strip both prefix and mount path', async () => { + const sdkApp = new Elysia({ prefix: '/sdk' }).mount( + '/problems-domain', + (request) => { + return Response.json({ path: new URL(request.url).pathname }) + } + ) + + const app = new Elysia().use(sdkApp) + + const response = await app + .handle( + new Request('http://localhost/sdk/problems-domain/problems') + ) + .then((x) => x.json() as Promise<{ path: string }>) + + expect(response.path).toBe('/problems') + }) })