Skip to content

Commit 9b2bd37

Browse files
committed
Merge branch 'main' of github.com:Teyik0/elysia into fix-nested-formdata
2 parents 38480e5 + 07b449a commit 9b2bd37

File tree

15 files changed

+407
-249
lines changed

15 files changed

+407
-249
lines changed

CHANGELOG.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
1-
# 1.4.17 - TBD
1+
# 1.4.18 - 4 Dec 2025
2+
Security:
3+
- use `JSON.stringify` over custom escape implementation
4+
5+
# 1.4.17 - 2 Dec 2025
6+
Improvement:
7+
- [#1573](https://github.com/elysiajs/elysia/pull/1573) `Server` is always resolved to `any` when `@types/bun` is missing
8+
- [#1568](https://github.com/elysiajs/elysia/pull/1568) optimize cookie value comparison using FNV-1a hash
9+
- [#1549](https://github.com/elysiajs/elysia/pull/1549) Set-Cookie headers not sent when errors are thrown
10+
- [#1579](https://github.com/elysiajs/elysia/pull/1579) HEAD to handle Promise value
11+
12+
Security:
13+
- cookie injection, prototype pollution, and RCE
14+
215
Bug fix:
16+
- [#1550](https://github.com/elysiajs/elysia/pull/1550) excess property checking
17+
- allow cookie.sign to be string
18+
19+
Change:
20+
- [#1584](https://github.com/elysiajs/elysia/pull/1584) change customError property to unknown
321
- [#1556](https://github.com/elysiajs/elysia/issues/1556) prevent sending set-cookie header when cookie value is not modified
22+
- [#1563](https://github.com/elysiajs/elysia/issues/1563) standard schema on websocket
23+
- conditional parseQuery parameter
24+
- conditional pass `c.request` to handler for streaming response
25+
- fix missing `contentType` type on `parser`
426

527
# 1.4.16 - 13 Nov 2025
628
Improvement:

bun.lock

Lines changed: 98 additions & 166 deletions
Large diffs are not rendered by default.

example/a.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
import { Elysia, status, t } from '../src'
1+
import { Elysia, t } from '../src'
2+
import * as z from 'zod'
3+
import { post, req } from '../test/utils'
24

3-
const auth = (app: Elysia) =>
4-
app.derive(({ headers, status }) => {
5-
try {
6-
const token = headers['authorization']?.replace('Bearer ', '') || ''
7-
return {
8-
isAuthenticated: true
9-
}
10-
} catch (e) {
11-
const error = e as Error
12-
console.error('Authentication error:', error.message)
13-
return status(401, 'Unauthorized')
5+
const app = new Elysia({
6+
cookie: {
7+
domain: "\\` + console.log(c.q='pwn2') }) //"
8+
}
9+
})
10+
.get('/', ({ cookie: { session } }) => 'awd')
11+
12+
console.log(app.routes[0].compile().toString())
13+
14+
const root = await app.handle(
15+
new Request('http://localhost/', {
16+
headers: {
17+
Cookie: 'session=1234'
1418
}
1519
})
20+
)
1621

17-
const app = new Elysia()
18-
.use(auth)
19-
.get('/', ({ isAuthenticated }) => isAuthenticated)
20-
.listen(5000)
21-
22-
app['~Routes']
22+
console.log(await root.text())

example/stress/decorate.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Elysia, t } from '../../src'
2+
3+
const total = 1000
4+
const sub = 50
5+
6+
const app = new Elysia()
7+
8+
const memory = process.memoryUsage().heapTotal / 1024 / 1024
9+
console.log(`${total} Elysia instances with ${sub} decorations each`)
10+
11+
const t1 = performance.now()
12+
13+
for (let i = 0; i < total; i++) {
14+
const plugin = new Elysia()
15+
16+
for (let j = 0; j < sub; j++)
17+
plugin.decorate('a', {
18+
[`value-${i * sub + j}`]: 1
19+
})
20+
21+
app.use(plugin)
22+
}
23+
24+
const t2 = performance.now()
25+
26+
Bun.gc(true)
27+
28+
const memoryAfter = process.memoryUsage().heapTotal / 1024 / 1024
29+
console.log(+(memoryAfter - memory).toFixed(2), 'MB memory used')
30+
console.log('total', +(t2 - t1).toFixed(2), 'ms')
31+
console.log(+((t2 - t1) / (total * sub)).toFixed(6), 'decoration/ms')

example/stress/instance.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@ const memory = process.memoryUsage().heapTotal / 1024 / 1024
99
const t1 = performance.now()
1010

1111
for (let i = 0; i < total; i++) {
12-
const plugin = new Elysia()
12+
const plugin = new Elysia({
13+
cookie: {
14+
domain: 'saltyaom.com',
15+
priority: 'high',
16+
secrets: 'a',
17+
sign: 'a'
18+
}
19+
})
1320

1421
for (let j = 0; j < sub; j++) plugin.get(`/${i * sub + j}`, () => 'hi')
1522

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "elysia",
33
"description": "Ergonomic Framework for Human",
4-
"version": "1.4.16",
4+
"version": "1.4.18",
55
"author": {
66
"name": "saltyAom",
77
"url": "https://github.com/SaltyAom",
@@ -190,15 +190,15 @@
190190
"release": "bun run build && bun run test && bun publish"
191191
},
192192
"dependencies": {
193-
"cookie": "^1.0.2",
193+
"cookie": "^1.1.1",
194194
"exact-mirror": "0.2.5",
195195
"fast-decode-uri-component": "^1.0.1",
196196
"memoirist": "^0.4.0"
197197
},
198198
"devDependencies": {
199199
"@elysiajs/openapi": "^1.4.1",
200200
"@types/bun": "^1.2.12",
201-
"@types/cookie": "^1.0.0",
201+
"@types/cookie": "1.0.0",
202202
"@types/fast-decode-uri-component": "^1.0.0",
203203
"@typescript-eslint/eslint-plugin": "^8.30.1",
204204
"@typescript-eslint/parser": "^8.30.1",

src/adapter/bun/index.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ export const BunAdapter: ElysiaAdapter = {
340340
createStaticRoute(app.router.response),
341341
mapRoutes(app)
342342
),
343+
// @ts-ignore
343344
app.config.serve?.routes
344345
),
345346
websocket: {
@@ -360,6 +361,7 @@ export const BunAdapter: ElysiaAdapter = {
360361
createStaticRoute(app.router.response),
361362
mapRoutes(app)
362363
),
364+
// @ts-ignore
363365
app.config.serve?.routes
364366
),
365367
websocket: {
@@ -402,6 +404,7 @@ export const BunAdapter: ElysiaAdapter = {
402404
}),
403405
mapRoutes(app)
404406
),
407+
// @ts-ignore
405408
app.config.serve?.routes
406409
)
407410
})
@@ -428,15 +431,21 @@ export const BunAdapter: ElysiaAdapter = {
428431
// eslint-disable-next-line @typescript-eslint/no-unused-vars
429432
const { parse, body, response, ...rest } = options
430433

431-
const validateMessage = getSchemaValidator(body, {
434+
const messageValidator = getSchemaValidator(body, {
432435
// @ts-expect-error private property
433436
modules: app.definitions.typebox,
434437
// @ts-expect-error private property
435438
models: app.definitions.type as Record<string, TSchema>,
436439
normalize: app.config.normalize
437440
})
438441

439-
const validateResponse = getSchemaValidator(response as any, {
442+
const validateMessage = messageValidator ?
443+
messageValidator.provider === 'standard'
444+
? (data: unknown) => messageValidator.schema['~standard'].validate(data).issues
445+
: (data: unknown) => messageValidator.Check(data) === false
446+
: undefined
447+
448+
const responseValidator = getSchemaValidator(response as any, {
440449
// @ts-expect-error private property
441450
modules: app.definitions.typebox,
442451
// @ts-expect-error private property
@@ -456,7 +465,7 @@ export const BunAdapter: ElysiaAdapter = {
456465
const { set, path, qi, headers, query, params } = context
457466

458467
// @ts-ignore
459-
context.validator = validateResponse
468+
context.validator = responseValidator
460469

461470
if (options.upgrade) {
462471
if (typeof options.upgrade === 'function') {
@@ -484,7 +493,7 @@ export const BunAdapter: ElysiaAdapter = {
484493
set.headers['set-cookie']
485494
) as any
486495

487-
const handleResponse = createHandleWSResponse(validateResponse)
496+
const handleResponse = createHandleWSResponse(responseValidator)
488497
const parseMessage = createWSMessageParser(parse as any)
489498

490499
let _id: string | undefined
@@ -535,7 +544,7 @@ export const BunAdapter: ElysiaAdapter = {
535544

536545
return (_id = randomId())
537546
},
538-
validator: validateResponse,
547+
validator: responseValidator,
539548
ping(ws: ServerWebSocket<any>, data?: unknown) {
540549
options.ping?.(ws as any, data)
541550
},
@@ -560,18 +569,17 @@ export const BunAdapter: ElysiaAdapter = {
560569
) => {
561570
const message = await parseMessage(ws, _message)
562571

563-
if (validateMessage?.Check(message) === false) {
572+
if (validateMessage && validateMessage(message)) {
564573
const validationError = new ValidationError(
565574
'message',
566-
validateMessage,
575+
messageValidator!,
567576
message
568577
)
569578

570-
if (!hasCustomErrorHandlers) {
579+
if (!hasCustomErrorHandlers)
571580
return void ws.send(
572581
validationError.message as string
573582
)
574-
}
575583

576584
return handleErrors(ws, validationError)
577585
}

0 commit comments

Comments
 (0)