feat: enable to get internal "getResponseState" function at Node.js v24.x#241
feat: enable to get internal "getResponseState" function at Node.js v24.x#241usualoma wants to merge 3 commits intohonojs:mainfrom
Conversation
|
Hi @yusukebe, I believe that the only way to resolve this issue is to proceed as follows. $ node --import @hono/node-server/setup ./app.mjsDo you think it is necessary to optimise in this complex manner? The |
|
Sorry for being late. I'm a little busy now and will comment on it later. Thanks. |
|
Hi @usualoma ! I am taking several benchmarks. I want to confirm in which cases there is a difference between using |
|
Hi @yusukebe, Thank you for your comment. We can see the difference in the following application. (The key point is import { serve } from '@hono/node-server'
import { Hono } from 'hono'
const app = new Hono()
app.get('/', () => {
const res = new Response('foo')
res.headers.set('x-foo', 'bar')
return res
})
serve({
fetch: app.fetch,
port: 3003,
})with
|
|
Hi @usualoma Thank you for the answer! This is a little bit difficult to decide. But it's okay to merge this PR! I also took a benchmark. I can't say it too loudly, but... I believe the most important aspect of benchmarks is comparing them with other frameworks (not comparing Hono itself). In practical use, the difference may not be significant because the neck will be in other places, but when compared with other frameworks, it becomes important. In the current Also, if users have problems in the real world, I think it's a good idea to use So, this PR is good. Can you make this PR ready and ping me? The following are just references. I created an app that performs header addition using Hono, Express, and Fastify, and took benchmarks. // Hono
app.get('/', (c) => {
const res = new Response('hi')
res.headers.set('x-foo', 'bar')
return res
})// Express
import express from 'express'
const app = express()
const port = 3001
app.get('/', (req, res) => {
res.set('x-foo', 'bar')
res.send('H!')
})
app.listen(port)// Fastify
import Fastify from 'fastify'
const fastify = Fastify({ logger: false })
fastify.get('/', async (request, reply) => {
reply.header('x-foo', 'bar')
return 'H!'
})
fastify.listen({ port: 3002 })The result is as follows. If you don't include The following is an example using app.get('/', (c) => {
c.header('x-foo', 'bar')
return c.text('H!')
})As expected, using |
|
Hi @yusukebe, Thank you for reviewing and confirming the performance! Is it common for headers to be modified?As @yusukebe mentioned, returning Headers and status codes are frequently referenced.Middleware probably mainly references (and modifies) It may not be necessary to refer to the internal data structure.Even if we refer to Current thoughtsI have been considering this PR to apply the same approach as @yusukebe I'm sorry to present another proposal. What do you think? |
|
Hi @usualoma ! #242 is great! I feel that the implementation of #242 seems to be simpler than the current implementation. I thought it could also cache the |
Bump @hono/node-server from ^1.3.3 (resolved 1.13.5) to ^1.14.2 (resolved 1.19.14) to fix "Failed to find Response internal state key" error on Node.js v24. Root cause: Node v24 ships a newer Undici that changed how Response internal state is accessed. Fixed upstream in honojs/node-server#241, released in @hono/node-server@1.14.2. Closes Portkey-AI#1604


fixes #240
With this PR, you will be able to apply optimisations to access internal data in v24 by executing the following.
What is this?
As pointed out by @timokoessler in #240, in Node.js v24.x, due to changes in nodejs/undici@45dceea, it is no longer possible to retrieve internal data using the previous node-server method.
Even when internal data cannot be retrieved, node-server continues to function normally; however, this may result in performance degradation for certain applications.
Another way to get internal data
This change to ‘undici’ has made it more difficult to obtain than before, but there are ways to do so. If you execute the following code snippet in v24, you will see that it can be obtained.
The difficulty of making this code work
In Node.js, the Response class is dynamically initialised when
global.Responseis referenced.This means that the code snippet above must be executed before
global.Responseis referenced for the first time. However, when executing.mtsor.mjsfiles,global.Responseis initialised during import resolution in most applications, so simply writing the code inside node-server will not work as expected.To ensure that it works correctly, users must explicitly specify the
--importoption at runtime.The option of giving up this optimisation
This optimisation was implemented in #145, but even without it, the speed in the ‘best case’ does not decrease. Therefore, I think there is an option to avoid making it as complex as in this PR and instead stop the optimisation that directly retrieves internal data to speed things up.
(However, if there is code that modifies the response headers, it will not achieve the ‘best case’ scenario and will remain a target for this optimisation, so I believe this optimisation applies to a fairly large number of applications.)