-
-
Notifications
You must be signed in to change notification settings - Fork 427
Description
What version of Elysia is running?
1.4.18
What platform is your computer?
Linux 6.12.61-1-MANJARO x86_64 unknown
What environment are you using
bun@1.3.3
Are you using dynamic mode?
no
What steps can reproduce the bug?
- Create an Elysia instance with a prefix
- Mount an external handler that relies on cookie headers (e.g., better-auth)
- Send a request with Cookie header
- The mounted handler receives undefined cookie header
Code example:
import { betterAuth } from 'better-auth';
import { openAPI } from 'better-auth/plugins';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { db } from '@/db';
import * as models from '@/models';
import { config } from '@/config';
import { getCorsOrigin } from '@/utils/getCorsOrigin';
const adapter = drizzleAdapter(db, {
provider: 'pg',
schema: {
user: models.user,
account: models.account,
session: models.session,
verificationToken: models.verification,
},
});
export const auth = betterAuth({
database: adapter,
secret: config.AUTH_SECRET,
origin: config.AUTH_ORIGIN, // http://localhost:5173
emailAndPassword: {
enabled: true,
},
plugins: [openAPI()],
trustedOrigins: getCorsOrigin(), // ['http://localhost:5173']
advanced: {
useSecureCookies: false,
defaultCookieAttributes: {
sameSite: 'lax' as const,
secure: false,
httpOnly: true,
partitioned: false,
},
},
session: {
cookieCache: {
enabled: true,
maxAge: 5 * 60,
},
},
});import Elysia from 'elysia';
import { auth } from './auth.config'; // better-auth instance
// This DOESN'T work - cookie header is undefined
const app = new Elysia({ prefix: '/auth' })
.mount(auth.handler)
.listen(3000);
// Test with:
// curl -H "Cookie: session_token=abc123" http://localhost:3000/auth/get-session
// Result: Cookie header is undefined in auth.handlerWhat is the expected behavior?
Mounted handlers should receive properly parsed request headers, including the cookie header, without requiring any workarounds.
When sending a request with Cookie: session=xyz header, the mounted handler should be able to access headers.cookie and receive the value "session=xyz".
This should work the same way as regular route handlers defined with .get(), .post(), etc.
What do you see instead?
The cookie header is undefined in mounted handlers unless explicitly accessed in an onRequest hook before mounting.
Different scenarios:
❌ No onRequest hook:
.mount(auth.handler) // headers.cookie = undefined❌ Empty onRequest hook:
.onRequest(() => {})
.mount(auth.handler) // headers.cookie = undefined✅ Accessing headers.cookie in onRequest:
.onRequest(({ headers }) => {
void headers.cookie; // Forces parsing
})
.mount(auth.handler) // headers.cookie = "session=xyz"✅ Using console.log (forces synchronization):
.onRequest(({ headers }) => {
console.log(headers.cookie);
})
.mount(auth.handler) // headers.cookie = "session=xyz"This behavior suggests a race condition or lazy initialization where headers are not parsed/available until explicitly accessed.
Additional information
Current workaround:
.onRequest(({ headers }) => {
// WORKAROUND: Force headers parsing before mounting
const _ = request.headers.get('cookie');
})
.mount(handler)Impact:
This breaks authentication flows when using:
- better-auth
- lucia-auth
- Any handler expecting cookies for session management
Additional observations:
- Issue only occurs with
.mount(), not with regular.get(),.post()handlers - Issue occurs regardless of whether the mounted handler is from an external library or locally defined
- Both
console.log()and explicitheaders.cookieaccess fix the issue - Empty hooks (
() => {}) do NOT fix the issue - Suggests the problem is in how Elysia handles context passing between hooks and mounted handlers
Related code:
The issue appears to be in the middleware chain initialization when using .mount(). Headers might be lazily evaluated and not properly passed to mounted handlers until accessed.
Have you try removing the node_modules and bun.lockb and try again yet?
no