fix(api): stop bounding request body receipt at the header timeout (#2245)

This commit is contained in:
Hampus
2026-08-31 15:36:54 +02:00
committed by GitHub
parent b4a2af75d0
commit 4b9964bc89
3 changed files with 50 additions and 2 deletions
+5 -1
View File
@@ -4,7 +4,8 @@ import {applyFluxerVersionHeader} from '@fluxer/hono/src/middleware/VersionHeade
import {type Http2Bindings, type HttpBindings, type ServerType, serve} from '@hono/node-server';
import type {Env, Hono} from 'hono';
const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
const DEFAULT_HEADERS_TIMEOUT_MS = 30_000;
const DEFAULT_REQUEST_TIMEOUT_MS = 120_000;
const DEFAULT_KEEP_ALIVE_TIMEOUT_MS = 125_000;
const DEFAULT_MAX_REQUESTS_PER_SOCKET = 1_000;
@@ -12,6 +13,7 @@ interface ServerOptions {
port: number;
hostname?: string;
onListen?: (info: {address: string; port: number}) => void;
headersTimeoutMs?: number;
requestTimeoutMs?: number;
keepAliveTimeoutMs?: number;
maxRequestsPerSocket?: number;
@@ -28,6 +30,7 @@ export function createServer<E extends Env = Env>(app: Hono<E>, options: ServerO
port,
hostname,
onListen,
headersTimeoutMs = DEFAULT_HEADERS_TIMEOUT_MS,
requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS,
keepAliveTimeoutMs = DEFAULT_KEEP_ALIVE_TIMEOUT_MS,
maxRequestsPerSocket = DEFAULT_MAX_REQUESTS_PER_SOCKET,
@@ -39,6 +42,7 @@ export function createServer<E extends Env = Env>(app: Hono<E>, options: ServerO
...(hostname !== undefined && {hostname}),
serverOptions: {
keepAliveTimeout: keepAliveTimeoutMs,
headersTimeout: requestTimeoutMs > 0 ? Math.min(headersTimeoutMs, requestTimeoutMs) : headersTimeoutMs,
requestTimeout: requestTimeoutMs,
},
},
+1 -1
View File
@@ -42,7 +42,7 @@ describe('Server limits', () => {
const listening = await listen({port: 0});
server = listening.server;
const httpServer = server as Server;
expect(httpServer.requestTimeout).toBe(30_000);
expect(httpServer.requestTimeout).toBe(120_000);
expect(httpServer.keepAliveTimeout).toBe(125_000);
expect(httpServer.maxRequestsPerSocket).toBe(1_000);
expect(httpServer.headersTimeout).toBeLessThanOrEqual(httpServer.requestTimeout);
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {Hono} from 'hono';
import {afterEach, describe, expect, it} from 'vitest';
import {createServer} from '../Server';
const servers: Array<{close: (cb: () => void) => void}> = [];
afterEach(async () => {
await Promise.all(servers.splice(0).map((s) => new Promise<void>((r) => s.close(() => r()))));
});
function listen(options: Parameters<typeof createServer>[1]) {
const app = new Hono();
app.post('/echo', async (ctx) => ctx.text(String((await ctx.req.text()).length)));
const server = createServer(app, options) as never as {
close: (cb: () => void) => void;
address: () => {port: number};
headersTimeout: number;
requestTimeout: number;
};
servers.push(server);
return server;
}
describe('createServer timeouts', () => {
it('separates the header timeout from the total request timeout', () => {
const server = listen({port: 0});
expect(server.headersTimeout).toBe(30_000);
expect(server.requestTimeout).toBe(120_000);
});
it('lets both be overridden', () => {
const server = listen({port: 0, headersTimeoutMs: 1_000, requestTimeoutMs: 2_000});
expect(server.headersTimeout).toBe(1_000);
expect(server.requestTimeout).toBe(2_000);
});
it('never lets the header timeout exceed the request timeout', () => {
const server = listen({port: 0, requestTimeoutMs: 5_000});
expect(server.requestTimeout).toBe(5_000);
expect(server.headersTimeout).toBeLessThanOrEqual(server.requestTimeout);
});
});