You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by "allthingssecurity (via GitHub)" <gi...@apache.org> on 2026/10/06 00:06:19 UTC

[PR] CAMEL-25133: camel-http-common - set the Content-Length of a non-chunked response as a long [camel]

allthingssecurity opened a new pull request, #27397:
URL: https://github.com/apache/camel/pull/27397

   # Description
   
   [CAMEL-25133](https://issues.apache.org/jira/browse/CAMEL-25133)
   
   `DefaultHttpBinding.doWriteDirectResponse` sized a non-chunked response with `int len = copyStream(...)` and `response.setContentLength(len)`. `IOHelper.copy` returns an `int`: for a body of 2 GiB or more it used to wrap to a negative value, and since CAMEL-25023 (#26892) it is clamped to `Integer.MAX_VALUE`, so the `Content-Length` header was wrong either way. @davsclaus raised it in the review of #26892 and @oscerd filed this ticket, suggesting to take the length as a `long` from the `CachedOutputStream` the body was copied into and to use `setContentLengthLong`.
   
   This change:
   - takes the length from the `StreamCache` of the `CachedOutputStream` (`newStreamCache().length()`, a `long`: the byte count in memory, the file length once spooled) and sets it with `setContentLengthLong` (Servlet 3.1+). `CachedOutputStream` itself only keeps a private `int` count, so the cache is the place where the length is available as a `long` without changing camel-support;
   - the spooled body is then copied to the response from that same cache, instead of opening a second one with `getInputStream()`;
   - that copy now uses the response buffer size, like the other copies in the class, instead of the length (it was passed as the buffer size, which cannot be a `long`). `IOHelper.copy` raises the buffer to what the stream reports as `available()` and caps it at 256 KiB, so for a spooled body of more than 256 KiB the buffer is 256 KiB as before.
   
   Why the length of the `StreamCache` and not a new getter on `CachedOutputStream`: its byte count is an `int` field that itself wraps past 2 GiB, so a `long` getter would mean changing camel-support; the cache already gives the length as a `long` (the byte count in memory, `File.length()` once spooled). With `spoolCipher` set, the spool file has the length of the body because the documented ciphers are stream ciphers ("a valid stream or 8-bit cipher name such as RC4, AES/CTR/NoPadding"). In memory `newStreamCache()` shares the buffer (no copy).
   
   This touches `doWriteDirectResponse` like the change for a String response in the charset of the Content-Type (CAMEL-25316, opened at the same time); the two merge without conflict and the camel-http-common, camel-servlet and camel-jetty tests pass with both applied.
   
   Note: a body of 2 GiB or more reaches this code only with spooling enabled (`spoolEnabled=true`, off by default in Camel 4): otherwise `CachedOutputStream` keeps the body in a byte array, which cannot hold 2 GiB. No upgrade guide entry, as the header only changes for those responses.
   
   Tests: new `DefaultHttpBindingContentLengthTest` (Mockito added as a test dependency of camel-http-common):
   - a response of 3 GiB without allocating or writing it: `mockConstruction` makes the `CachedOutputStream` report a spooled cache whose `length()` is 3 GiB while it holds a few bytes; the test verifies `setContentLengthLong(3221225472)`, that `setContentLength(int)` is not called, and the bytes sent (this test is tied to how the length is obtained, `newStreamCache().length()`; the other two are not);
   - a really spooled response (spool threshold 1 byte, temp spool directory) and an in-memory one: `setContentLengthLong` with the body length, and the body sent unchanged.
   
   Without the change all 3 fail (twice, `Wanted but not invoked: setContentLengthLong(...)`). With the change: camel-http-common 39 tests, camel-servlet 102 tests (2 skipped), camel-jetty 395 tests (23 skipped) except `JettyXsltHttpTemplateTest`, which fails on my machine with and without the change (`Connection reset` from `0.0.0.0`), and the camel-http test classes that reference `DefaultHttpBinding` (4 tests) pass.
   
   # Target
   
   - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch)
   
   # Tracking
   - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it).
   
   # Apache Camel coding standards and style
   
   - [x] I checked that each commit in the pull request has a meaningful subject line and body.
   - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes.
     (I built and tested the affected module, including the formatter and import-sort plugins. I did not run the full root build.)
   
   # AI-assisted contributions
   
   - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used.
     This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer.
   
   _Claude Code on behalf of allthingssecurity_
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25133: camel-http-common - set the Content-Length of a non-chunked response as a long [camel]

Posted by "allthingssecurity (via GitHub)" <gi...@apache.org>.
allthingssecurity commented on code in PR #27397:
URL: https://github.com/apache/camel/pull/27397#discussion_r4191905905


##########
components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java:
##########
@@ -543,9 +543,12 @@ protected void doWriteDirectResponse(Message message, HttpServletResponse respon
                 CachedOutputStream stream = new CachedOutputStream(exchange);
                 try {
                     // copy directly from input stream to the cached output stream to get the content length
-                    int len = copyStream(is, stream, response.getBufferSize());
-                    // we need to setup the length if message is not chucked
-                    response.setContentLength(len);
+                    copyStream(is, stream, response.getBufferSize());
+                    // we need to setup the length if message is not chucked. Take it as a long from the cache, as the
+                    // int count of copyStream cannot hold the length of a response of 2 GiB or more
+                    StreamCache cache = stream.newStreamCache();
+                    long len = cache.length();
+                    response.setContentLengthLong(len);

Review Comment:
   Thanks, good point: `FileInputStreamCache.length()` is the spool file length, so with a padded block cipher it would be larger than the body. Added a comment on the assumption in aab87c3692cb (the docs only allow stream or 8-bit ciphers).
   
   _Claude Code on behalf of allthingssecurity_



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25133: camel-http-common - set the Content-Length of a non-chunked response as a long [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #27397:
URL: https://github.com/apache/camel/pull/27397#issuecomment-6010007557

   :star2: Thank you for your contribution to the Apache Camel project! :star2:
     :robot: CI automation will test this PR automatically.
   
     :camel: Apache Camel Committers, please review the following items:
   
     * First-time contributors **require MANUAL approval** for the GitHub Actions to run
     * You can use the command `/component-test (camel-)component-name1 (camel-)component-name2..` to request a test from the test bot although they are normally detected and executed by CI.
     * You can label PRs using `skip-tests` and `test-dependents` to fine-tune the checks executed by this PR.
     * Build and test logs are available in the summary page. **Only** [Apache Camel committers](https://camel.apache.org/community/team/#committers) have access to the summary.
     
     :warning: Be careful when sharing logs. Review their contents before sharing them publicly.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25133: camel-http-common - set the Content-Length of a non-chunked response as a long [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on code in PR #27397:
URL: https://github.com/apache/camel/pull/27397#discussion_r4191865041


##########
components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java:
##########
@@ -543,9 +543,12 @@ protected void doWriteDirectResponse(Message message, HttpServletResponse respon
                 CachedOutputStream stream = new CachedOutputStream(exchange);
                 try {
                     // copy directly from input stream to the cached output stream to get the content length
-                    int len = copyStream(is, stream, response.getBufferSize());
-                    // we need to setup the length if message is not chucked
-                    response.setContentLength(len);
+                    copyStream(is, stream, response.getBufferSize());
+                    // we need to setup the length if message is not chucked. Take it as a long from the cache, as the
+                    // int count of copyStream cannot hold the length of a response of 2 GiB or more
+                    StreamCache cache = stream.newStreamCache();
+                    long len = cache.length();
+                    response.setContentLengthLong(len);

Review Comment:
   Minor: with `spoolCipher` set to a padded block cipher (e.g. `AES`, which defaults to PKCS5 padding), the spool file is longer than the body, so this length would be too large, where the old byte count was right. The docs only allow stream or 8-bit ciphers, so not blocking, but a one-line comment noting the assumption would help the next reader.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25133: camel-http-common - set the Content-Length of a non-chunked response as a long [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus merged PR #27397:
URL: https://github.com/apache/camel/pull/27397


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25133: camel-http-common - set the Content-Length of a non-chunked response as a long [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #27397:
URL: https://github.com/apache/camel/pull/27397#issuecomment-6010171323

   <!-- ci-tested-modules -->
   :test_tube: **CI tested the following changed modules:**
   
   - `components/camel-http-common`
   
   > :information_source: Dependent modules were not tested because the total number of affected modules exceeded the threshold (50). Use the `test-dependents` label to force testing all dependents.
   
   ---
   
   <details><summary>:microscope: Scalpel shadow comparison — Scalpel: 78 of 698 tested, 1 compile-only — current: 78 all tested</summary>
   
   [Maveniverse Scalpel](https://github.com/maveniverse/scalpel) detected **78 affected modules** (current approach: 78).
   
   **Skip-tests mode would test 78 modules** (1 direct + 0 downstream), **skip tests for 1** (generated code, meta-modules)
   
   <details><summary>Modules Scalpel would test (78)</summary>
   
   - `camel-a2a` ← depends on affected reactor module org.apache.camel:camel-platform-http-vertx
   - `camel-ai-observability` ← depends on affected reactor module org.apache.camel:camel-telemetry
   - `camel-as2` ← depends on affected reactor module org.apache.camel:camel-jetty
   - `camel-atmosphere-websocket` ← depends on affected reactor module org.apache.camel:camel-servlet
   - `camel-clickup` ← depends on affected reactor module org.apache.camel:camel-netty-http
   - `camel-consul` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-cxf-rest` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-cxf-soap` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-cxf-spring-rest` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-cxf-spring-soap` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-cxf-spring-transport` ← depends on affected reactor module org.apache.camel:camel-cxf-transport
   - `camel-cxf-transport` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-graphql` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-http` ← depends on affected reactor module org.apache.camel:camel-http-common
   - `camel-http-common` ← components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java, components/camel-http-common/src/test/java/org/apache/camel/http/common/DefaultHttpBindingContentLengthTest.java, own pom components/camel-http-common/pom.xml changed
   - `camel-java-joor-dsl` ← depends on affected reactor module org.apache.camel:camel-telegram
   - `camel-jbang-mcp` ← depends on affected reactor module org.apache.camel:camel-xml-io-dsl
   - `camel-jbang-plugin-mcp` ← depends on affected reactor module org.apache.camel:camel-jbang-core
   - `camel-jbang-plugin-route-parser` ← depends on affected reactor module org.apache.camel:camel-route-parser
   - `camel-jbang-plugin-tui` ← depends on affected reactor module org.apache.camel:camel-yaml-dsl-validator
   - `camel-jbang-plugin-validate` ← depends on affected reactor module org.apache.camel:camel-yaml-dsl-validator
   - `camel-jetty` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-jetty-common` ← depends on affected reactor module org.apache.camel:camel-http-common
   - `camel-jsonpath` ← depends on affected reactor module org.apache.camel:camel-platform-http-vertx
   - `camel-kamelet` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-knative-http` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-kubernetes` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-langchain4j-agent` ← depends on affected reactor module org.apache.camel:camel-telemetry
   - `camel-langchain4j-chat` ← depends on affected reactor module org.apache.camel:camel-telemetry
   - `camel-langchain4j-embeddings` ← depends on affected reactor module org.apache.camel:camel-telemetry
   - `camel-langchain4j-embeddingstore` ← depends on affected reactor module org.apache.camel:camel-langchain4j-embeddings
   - `camel-launcher-container` ← depends on affected reactor module org.apache.camel:camel-launcher
   - `camel-lra` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-mcp-server` ← depends on affected reactor module org.apache.camel:camel-openai
   - `camel-micrometer-observability` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-micrometer-prometheus` ← depends on affected reactor module org.apache.camel:camel-platform-http-main
   - `camel-netty-http` ← depends on affected reactor module org.apache.camel:camel-jetty
   - `camel-oauth` ← depends on affected reactor module org.apache.camel:camel-servlet
   - `camel-observability-services` ← depends on affected reactor module org.apache.camel:camel-opentelemetry2
   - `camel-odata` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-openai` ← depends on affected reactor module org.apache.camel:camel-platform-http-vertx
   - `camel-openapi-validator` ← depends on affected reactor module org.apache.camel:camel-platform-http-vertx
   - `camel-opentelemetry` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-opentelemetry2` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-platform-http` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-platform-http-jolokia` ← depends on affected reactor module org.apache.camel:camel-platform-http
   - `camel-platform-http-main` ← depends on affected reactor module org.apache.camel:camel-platform-http-vertx
   - `camel-platform-http-vertx` ← depends on affected reactor module org.apache.camel:camel-vertx-http
   - `camel-quickfix` ← depends on affected reactor module org.apache.camel:camel-jetty
   - `camel-rest-openapi` ← depends on affected reactor module org.apache.camel:camel-vertx-http
   - `camel-rest-postman` ← depends on affected reactor module org.apache.camel:camel-vertx-http
   - `camel-restdsl-openapi-plugin` ← depends on affected reactor module org.apache.camel:camel-jetty
   - `camel-sap-netweaver` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-semantic` ← depends on affected reactor module org.apache.camel:camel-xml-io-dsl
   - `camel-servlet` ← depends on affected reactor module org.apache.camel:camel-http-common
   - `camel-slack` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-soap` ← depends on affected reactor module org.apache.camel:camel-cxf-soap
   - `camel-spring-ai-chat` ← depends on affected reactor module org.apache.camel:camel-telemetry
   - `camel-spring-rabbitmq` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-state-store` ← depends on affected reactor module org.apache.camel:camel-test-main-junit5
   - `camel-telegram` ← depends on affected reactor module org.apache.camel:camel-netty-http
   - `camel-telemetry` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-telemetry-dev` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-test-main-junit5` ← depends on affected reactor module org.apache.camel:camel-xml-io-dsl
   - `camel-test-main-junit6` ← depends on affected reactor module org.apache.camel:camel-xml-io-dsl
   - `camel-typesafe-ai` ← depends on affected reactor module org.apache.camel:camel-xml-io-dsl
   - `camel-undertow` ← depends on affected reactor module org.apache.camel:camel-http
   - `camel-undertow-spring-security` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-vertx-http` ← depends on affected reactor module org.apache.camel:camel-undertow
   - `camel-webhook` ← depends on affected reactor module org.apache.camel:camel-netty-http
   - `camel-whatsapp` ← depends on affected reactor module org.apache.camel:camel-netty-http
   - `camel-xml-io-dsl` ← depends on affected reactor module org.apache.camel:camel-kamelet
   - `camel-xml-jaxb-dsl` ← depends on affected reactor module org.apache.camel:camel-telegram
   - `camel-xml-jaxb-dsl-test-definition` ← depends on affected reactor module org.apache.camel:camel-telegram
   - `camel-xml-jaxb-dsl-test-spring` ← depends on affected reactor module org.apache.camel:camel-telegram
   - `camel-yaml-dsl-validator` ← depends on affected reactor module org.apache.camel:camel-catalog
   - `camel-yaml-dsl-validator-maven-plugin` ← depends on affected reactor module org.apache.camel:camel-yaml-dsl-validator
   - `camel-zookeeper` ← depends on affected reactor module org.apache.camel:camel-undertow
   
   </details>
   
   <details><summary>Modules with tests skipped (1)</summary>
   
   - `camel-yaml-dsl-deserializers`
   
   </details>
   
   > :information_source: Shadow mode — Scalpel observes but does not affect test execution. [Learn more](https://github.com/maveniverse/scalpel)
   
   </details>
   
   ---
   :gear: [View full build and test results](https://github.com/apache/camel/actions/runs/37392198161)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org