Skip to content

Add configurable request header size to the HTTP Listener - #393

Open
pacmano1 wants to merge 3 commits into
OpenIntegrationEngine:mainfrom
pacmano1:feat/http-listener-request-header-size
Open

Add configurable request header size to the HTTP Listener#393
pacmano1 wants to merge 3 commits into
OpenIntegrationEngine:mainfrom
pacmano1:feat/http-listener-request-header-size

Conversation

@pacmano1

@pacmano1 pacmano1 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Closes #392.

Jetty caps the combined size of all request headers at 8192 bytes and answers anything larger with 431 Request Header Fields Too Large during header parsing, so the channel never sees the request. This adds a per-connector Request Header Size field.

The value is a String and resolves through the template replacer at channel start, like host, port and timeout already do.

Invalid values fail the connector

Addressing @mgaffigan's review. A value that does not resolve to a positive number now fails the connector at start rather than falling back to 8192:

String requestHeaderSizeValue = replacer.replaceValues(getConnectorProperties().getRequestHeaderSize(), channelId, channelName);
requestHeaderSize = NumberUtils.toInt(requestHeaderSizeValue, 0);

if (requestHeaderSize <= 0) {
    throw new ConnectorTaskException("Invalid request header size: " + requestHeaderSizeValue);
}

Falling back was a silent loss of the limit. Someone setting a cap lower than the default, to bound memory use or to stay within what a downstream component expects, would have had the higher default quietly restored.

Passing 0 as the NumberUtils default is what makes this one branch instead of two. An unparseable value, an unresolved template, zero and a negative all land on 0 and fail the same way, and the message carries the value as it resolved, so a broken substitution shows up as the literal ${...} text rather than a number.

Only requestHeaderSize changed. The pre-existing port, timeout and responseStatusCode fallbacks in this file have live channels behind them, so tightening those is a separate change.

Addressing @tonygermano's review, the Jetty HttpConfiguration is now built in a protected createHttpConfig(HttpReceiver) rather than inline in configureReceiver. An implementation that overrides configureReceiver can build its listener from the current defaults instead of repeating them, and picks up later additions for free. No behaviour change. TLSHttpConfiguration in the NovaMap TLS manager plugin extends this class and is the case in point: its non-TLS branch already delegates to super and gets the setting, while its TLS branch repeats two of the settings and misses the header size. Raised there as tls-manager-plugin#44; TLS listeners keep ignoring the setting until that lands.

Existing channels

Nothing happens to them on upgrade. A channel saved before this feature has no requestHeaderSize element, and XStream leaves the field null when it loads one, so getRequestHeaderSize() returns 8192 and the channel deploys and runs exactly as it did before. No migration runs and no stored channel is modified.

Open such a channel in the editor and the field shows 8192. That is the getter's answer rather than something read from the channel, so the element is only written the first time someone saves it. Until then an export of that channel still has no element.

The strict check only applies to a value that is actually present, so an absent one can never fail a deploy.

How to verify

Run on a live engine, HTTP Listener on port 9000, context path /test.

configured value result
10000 starts; 9945-byte header returns 200, 9950-byte returns 431
${headerSize} with $gc('headerSize','10000') in the deploy script starts; same 9945/9950 boundary, so the resolved value applied rather than the default
0 pushed via the REST API channel STOPPED, ConnectorTaskException: Invalid request header size: 0
${headerSize} with the deploy script cleared channel STOPPED, ConnectorTaskException: Invalid request header size: ${headerSize}
element stripped from the channel XML entirely starts on 8192, boundary drops accordingly

The ~55-byte gap between the configured value and the observed boundary is the request line plus Host, User-Agent and Accept.

The last three cannot be reached through the connector panel, which rejects them, so they were pushed through the REST API the way an import or an API-created channel would arrive.

Tests

12 across three classes: a real Jetty connector for 431 versus 200, a real receiver covering the resolution path including zero, negative, unparseable and an unresolved template, and a serialized-XML round trip proving a channel with no element still gets 8192. Removing the throw fails four tests; changing the default constant fails a third class.

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

Test Results

670 tests  +12   670 ✅ +12   2m 16s ⏱️ + 1m 12s
113 suites + 3     0 💤 ± 0 
113 files   + 3     0 ❌ ± 0 

Results for commit 22f16c0. ± Comparison against base commit ac3a398.

♻️ This comment has been updated with latest results.

@mgaffigan mgaffigan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: Does this really need to be a connector level config? Seems like it could be a much smaller change when coming from mirth.properties.

@pacmano1
pacmano1 force-pushed the feat/http-listener-request-header-size branch from cd4a6ba to 82dcd36 Compare July 31, 2026 16:12
@pacmano1
pacmano1 requested a review from mgaffigan July 31, 2026 16:22
mgaffigan
mgaffigan previously approved these changes Jul 31, 2026
Jetty caps the combined size of all request headers at 8192 bytes and
answers anything larger with 431 Request Header Fields Too Large, before
the channel sees the request. Add a per-connector Request Header Size
setting so that limit can be raised.

The value is a String so it can carry a template, resolved at channel
start the same way host, port and timeout already are. Channels saved
without the element fall back to 8192, so existing channels behave
exactly as before.

A non-positive size is clamped to the default because Jetty treats it as
no limit at all rather than rejecting requests, and the connector panel
cannot vet a channel that arrives through the REST API or an import.

Signed-off-by: Finnegan's Owner <44065187+pacmano1@users.noreply.github.com>
A request header size that does not resolve to a positive number now fails
the connector instead of falling back to the default.

Falling back was a silent loss of the limit. Someone setting a cap lower
than the default to bound memory use, or to keep header size within what a
downstream component expects, would have had the higher default quietly
restored. Passing 0 as the NumberUtils default means a value that cannot be
parsed, an unresolved template, zero and a negative all fail through the
same branch, and the message carries the value as it resolved.

Only requestHeaderSize is changed. The pre-existing port, timeout and
responseStatusCode fallbacks in this file have live channels behind them and
tightening those is a separate change.

Signed-off-by: Finnegan's Owner <44065187+pacmano1@users.noreply.github.com>
configureReceiver built the Jetty HttpConfiguration inline, so an
implementation overriding it had to repeat those settings and would not pick
up later additions to them.

Moving construction into a protected createHttpConfig lets a subclass build
its listener from the current defaults instead. TLSHttpConfiguration in the
NovaMap TLS manager plugin is the case in point: it extends this class, and
its TLS branch already repeats setSendServerVersion and setSendXPoweredBy
while missing the request header size entirely.

No behaviour change.

Signed-off-by: Finnegan's Owner <44065187+pacmano1@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[IDEA] Add Request Header Size on HTTP Listener

4 participants