[ORCA-77] Increase max header size - #8
Conversation
Node's 16 KB default rejects oversized request headers with a bodyless 431 before the request reaches any route, so it cannot be handled or logged in app code. Users running many browser extensions have exceeded it, making the tool unusable for them in every environment while working normally in incognito. Build the server explicitly rather than via app.listen so dev and production share one limit, and expose MAX_HTTP_HEADER_SIZE to adjust without a rebuild. Verified: a 20 KB request header returns 431 on the default and 200 with this change.
📝 WalkthroughSummary by CodeRabbit
Walkthrough
ChangesHTTP server startup
Estimated code review effort: 2 (Simple) | ~5 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Pull request overview
This PR increases the Node/HTTP server maximum request header size to reduce occurrences of bodyless 431 responses caused by oversized cookie/header payloads, allowing requests to reach Express/React Router where they can be handled and logged.
Changes:
- Swap
app.listen(...)for an explicitnode:httpserver withmaxHeaderSize. - Add
MAX_HTTP_HEADER_SIZEenv override with a default of32768bytes (32KB).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| process.env.NODE_ENV === 'production' ? 'http://0.0.0.0' : 'http://localhost'; | ||
|
|
||
| app.listen(port, () => console.log(host + ':' + port)); | ||
| const maxHeaderSize = Number(process.env.MAX_HTTP_HEADER_SIZE) || 32768; |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@server.mjs`:
- Line 49: Configure the ESLint environment for Node.js in the repository’s
ESLint configuration so the global process used by server.mjs is recognized.
Update the relevant ESLint settings without suppressing the undefined-variable
rule or changing maxHeaderSize.
- Line 49: Update the maxHeaderSize configuration to validate
MAX_HTTP_HEADER_SIZE before passing it to createServer: accept only finite,
valid integer values within Node’s supported range, and fall back to 32768 or
explicitly reject invalid input. Ensure values such as -1, 32768.5, and Infinity
cannot reach createServer.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| process.env.NODE_ENV === 'production' ? 'http://0.0.0.0' : 'http://localhost'; | ||
|
|
||
| app.listen(port, () => console.log(host + ':' + port)); | ||
| const maxHeaderSize = Number(process.env.MAX_HTTP_HEADER_SIZE) || 32768; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Resolve the ESLint process error.
The provided ESLint analysis reports process as undefined on this new line, so the repository lint command will fail. Configure Node globals for server.mjs in the ESLint configuration rather than suppressing the rule.
🧰 Tools
🪛 ESLint
[error] 49-49: 'process' is not defined.
(no-undef)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@server.mjs` at line 49, Configure the ESLint environment for Node.js in the
repository’s ESLint configuration so the global process used by server.mjs is
recognized. Update the relevant ESLint settings without suppressing the
undefined-variable rule or changing maxHeaderSize.
Source: Linters/SAST tools
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
node --input-type=module <<'NODE'
import { createServer } from 'node:http';
for (const maxHeaderSize of [-1, 32768.5, 32768]) {
try {
createServer({ maxHeaderSize });
console.log(maxHeaderSize, 'accepted');
} catch (error) {
console.log(maxHeaderSize, error.code ?? error.name);
}
}
NODERepository: tidepool-org/orca-remix
Length of output: 384
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and inspect server.mjs around the reported line.
if [ -f server.mjs ]; then
sed -n '1,90p' server.mjs | nl -ba
else
echo "server.mjs not found"
fi
# Probe Node's maxHeaderSize behavior for the exact env-related values and edge cases.
printf '\n--- Node createServer createServerOptions.maxHeaderSize behavior ---\n'
node --input-type=module <<'NODE'
import { createServer } from 'node:http';
const cases = [
'-1',
'32768.5',
'0',
'1',
'32768',
'not-a-number',
'',
'Infinity',
'-Infinity',
'1.0',
'1.1',
];
for (const raw of cases) {
const configured = Number(raw);
const maxHeaderSize = configured || 32768;
try {
const server = createServer({ maxHeaderSize });
server.close(() => console.log(`'${raw}' -> configured=${configured}, fallback=${maxHeaderSize}, accepted`));
} catch (error) {
console.log(`'${raw}' -> configured=${configured}, fallback=${maxHeaderSize}, rejected ${error.code ?? error.name}: ${error.message}`);
}
}
NODERepository: tidepool-org/orca-remix
Length of output: 201
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "PWD=$(pwd)"
echo "server.mjs exists=$(if [ -f server.mjs ]; then echo yes; else echo no; fi)"
# Locate and inspect server.mjs around the reported line.
if [ -f server.mjs ]; then
sed -n '1,100p' server.mjs
fi
echo
echo "--- Node createServer createServerOptions.maxHeaderSize behavior ---"
node --input-type=module <<'NODE'
import { createServer } from 'node:http';
const cases = [
'-1',
'32768.5',
'0',
'1',
'32768',
'not-a-number',
'',
'Infinity',
'-Infinity',
'1.0',
'1.1',
];
for (const raw of cases) {
const configured = Number(raw);
const maxHeaderSize = configured || 32768;
try {
const server = createServer({ maxHeaderSize });
server.close(() => console.log(`'${raw}' -> configured=${configured}, fallback=${maxHeaderSize}, accepted`));
} catch (error) {
console.log(`'${raw}' -> configured=${configured}, fallback=${maxHeaderSize}, rejected ${error.code ?? error.name}: ${error.message}`);
}
}
NODERepository: tidepool-org/orca-remix
Length of output: 2793
Validate MAX_HTTP_HEADER_SIZE before passing it to Node.
Number(...) || 32768 lets invalid truthy values like -1, 32768.5, or Infinity reach createServer({ maxHeaderSize }), where Node rejects them as out-of-range and prevents the server from starting. Reject invalid values explicitly or fall back to the default.
🧰 Tools
🪛 ESLint
[error] 49-49: 'process' is not defined.
(no-undef)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@server.mjs` at line 49, Update the maxHeaderSize configuration to validate
MAX_HTTP_HEADER_SIZE before passing it to createServer: accept only finite,
valid integer values within Node’s supported range, and fall back to 32768 or
explicitly reject invalid input. Ensure values such as -1, 32768.5, and Infinity
cannot reach createServer.
|
I'm going to close this PR - the actual fix for the 431 lied elsewhere. |
ORCA-77
Node's 16 KB default rejects oversized request headers with a bodyless 431 before the request reaches any route, so it cannot be handled or logged in app code.
This attempts to mitigate the issue by bumping up to 32kb, providing hopefully enough headroom for the application cookies (which have been optimized by pruning stale entries in ORCA-76, plus any extra overhead added by browser extensions that can impact the header size as well.