Follow-up surfaced in the #563 / #566 review (default request body limit raised 10MB → 20MB).
Problem
The tunnel proxy has its own hard-coded 10 MB cap that #563's body-limit change does not touch, so the tunnel path is now the bottleneck — and it's inconsistent in three ways.
src/tunnel/index.js:
const MAX_MESSAGE_SIZE = 10 * 1024 * 1024; // 10MB (line 82)
...
socket.on('message', (data) => {
const raw = Buffer.isBuffer(data) ? data : Buffer.from(data);
if (raw.byteLength > MAX_MESSAGE_SIZE) { // line 137
socket.send(JSON.stringify({ type: 'error', message: 'Message too large' }));
return;
}
1. Inconsistent with the new 20MB HTTP body default
config.defaults.bodyLimit is now 20 MiB (#563) and configurable via --body-limit / JSS_BODY_LIMIT. MAX_MESSAGE_SIZE is a separate, hard-coded 10 MB constant with no knob. A deployment that raises --body-limit to accept larger payloads still silently caps anything traversing a tunnel at 10 MB.
2. Direction-specific, and the cap bites responses
MAX_MESSAGE_SIZE is enforced only in socket.on('message') — i.e. messages the relay receives from the tunnel client, which are the response frames carrying the HTTP response body. So a tunnelled download (e.g. git clone/fetch of a repo, or any large GET) whose body exceeds the cap fails with Message too large. The request direction (relay→client, e.g. a push upload) is governed instead by the relay's HTTP bodyLimit on intake — a different limit on a different leg. The two legs of one tunnelled round-trip are bounded by two unrelated, unaligned numbers.
3. base64 framing overhead isn't accounted for
Bodies are base64-encoded into the JSON frames (tunnelReq.body = …toString('base64'), and the response side likewise). base64 inflates ~33%, so the effective content limit is ~7.5 MB, not 10 MB — and a body sized right at a configured limit won't fit once framed.
Suggested direction
- Derive the tunnel message cap from the effective
bodyLimit (plus base64 headroom, ~×1.4) instead of a separate constant, OR make it independently configurable and document the relationship.
- Apply a consistent bound to both legs (request frame out, response frame in) so a tunnelled round-trip has one predictable size budget.
- Account for base64 inflation so a payload at the body limit actually traverses the tunnel.
Refs
Follow-up surfaced in the #563 / #566 review (default request body limit raised 10MB → 20MB).
Problem
The tunnel proxy has its own hard-coded 10 MB cap that #563's body-limit change does not touch, so the tunnel path is now the bottleneck — and it's inconsistent in three ways.
src/tunnel/index.js:1. Inconsistent with the new 20MB HTTP body default
config.defaults.bodyLimitis now 20 MiB (#563) and configurable via--body-limit/JSS_BODY_LIMIT.MAX_MESSAGE_SIZEis a separate, hard-coded 10 MB constant with no knob. A deployment that raises--body-limitto accept larger payloads still silently caps anything traversing a tunnel at 10 MB.2. Direction-specific, and the cap bites responses
MAX_MESSAGE_SIZEis enforced only insocket.on('message')— i.e. messages the relay receives from the tunnel client, which are theresponseframes carrying the HTTP response body. So a tunnelled download (e.g.git clone/fetchof a repo, or any large GET) whose body exceeds the cap fails withMessage too large. The request direction (relay→client, e.g. a push upload) is governed instead by the relay's HTTPbodyLimiton intake — a different limit on a different leg. The two legs of one tunnelled round-trip are bounded by two unrelated, unaligned numbers.3. base64 framing overhead isn't accounted for
Bodies are base64-encoded into the JSON frames (
tunnelReq.body = …toString('base64'), and the response side likewise). base64 inflates ~33%, so the effective content limit is ~7.5 MB, not 10 MB — and a body sized right at a configured limit won't fit once framed.Suggested direction
bodyLimit(plus base64 headroom, ~×1.4) instead of a separate constant, OR make it independently configurable and document the relationship.Refs
--body-limitknob