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/07 00:06:33 UTC

[PR] CAMEL-25306: camel-rest-openapi, camel-rest-postman - Decode the path parameters of contract-first operations [camel]

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

   # Description
   
   [CAMEL-25306](https://issues.apache.org/jira/browse/CAMEL-25306)
   
   Reported by Serdar GΓΆkay, with a reproducer that serves the same route through a contract-first `rest-openapi` consumer and through the Rest DSL. `RestOpenApiProcessor` maps the operation's path placeholders from `Exchange.HTTP_PATH`, which is the raw request path (`RoutingContext.normalizedPath()` in camel-platform-http-vertx, the request URI in the Spring Boot engine). So a contract-first route got `id=A%221`, `X%20Y` or `caf%C3%A9`, while the Rest DSL route got `A"1`, `X Y` and `cafΓ©`. With `clientRequestValidation=true` the validator even checks the decoded value while the route gets the encoded text.
   
   As proposed in the ticket, `RestOpenApiProcessor` now passes a `BiConsumer` to the existing `HttpHelper.evalPlaceholders(BiConsumer, String, String)` overload, which decodes each value after the path has been split:
   - percent-encoded octets are decoded as UTF-8;
   - an encoded `/` stays inside its parameter, because the path is split before decoding (matching is still done on the raw path);
   - a `+` stays a `+`, since in a path it is a literal and only form-encoded query strings use it for a space;
   - a value with a malformed escape (such as `100%`) is kept as it is;
   - values without `%` are unchanged.
   
   The decoding is a new `HttpHelper.decodePathParameter(String)` in camel-http-base (the existing `evalPlaceholders` methods are unchanged, so the Rest DSL consumers are not affected). camel-rest-postman (`RestPostmanProcessor`, new in 4.23) built its headers the same way from `HTTP_PATH`, so it uses the same decoding now; as that component has not been released, its change needs no upgrade-guide note.
   
   Found and checked with a Lean 4 model of `evalPlaceholders` (including Java's `split("/")`) and of RFC 3986 segment encoding:
   - On main every value that needs an escape reaches the route still encoded.
   - For every template and all (ASCII, non-empty) values, the fix gives exactly the values the client encoded.
   - Decoding the whole path first would split `a%2Fb` into two parameters, and form decoding would turn `+` into a space.
   - The fix equals main for every value without `%`.
   
   This gives the same values as the Rest DSL. I checked it end to end with the Vert.x engine (camel-platform-http-vertx), with the reproducer of the ticket: a contract-first operation and a Rest DSL operation for `/items/{id}`, called with `A%221`, `X%20Y`, `caf%C3%A9`, `a+b`, `a%2Bb`, `%2541`, `a%2Fb`, `100%25`, `%7E1` and `a;x=y`. On main the contract-first values are still encoded (as in the ticket's table); with this change both consumers give the same value for every request, for example `%2541` gives `%41` (decoded once: the Vert.x engine only decodes unreserved characters in `HTTP_PATH`). The Spring Boot engine also decodes each segment after splitting for the Rest DSL.
   
   Tests: the new `RestOpenApiPathParameterDecodingTest` (11 cases) sends requests through `RestOpenApiProcessor`. 8 of them fail without the change (`expected: <A"1> but was: <A%221>`, `<cafΓ©>`/`<caf%C3%A9>`, `<a/b>`/`<a%2Fb>`, `<%41>`/`<%2541>`, ...). The `a+b`, `100%` and `plain` cases pass with and without the change. The new `RestPostmanPathParameterDecodingTest` (3 cases) fails without the change (`expected: <cafΓ©> but was: <caf%C3%A9>`, ...), and `HttpHelperTest.testDecodePathParameter` covers the helper. The `camel-http-base` (51 tests), `camel-rest-openapi` (176) and `camel-rest-postman` (173) modules pass, and so do the rest-openapi tests of camel-platform-http-vertx (run before the decoding moved to `HttpHelper`; the code is the same).
   
   As routes that decoded these headers themselves would now decode twice, the 4.23 upgrade guide has a short `=== camel-rest-openapi - path parameters are decoded` section.
   
   # 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 `components/camel-rest-openapi`, including the formatter and import-sort plugins. No generated files change. 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-25306: camel-rest-openapi, camel-rest-postman - Decode the path parameters of contract-first operations [camel]

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


##########
components/camel-rest-postman/src/test/java/org/apache/camel/component/rest/postman/RestPostmanPathParameterDecodingTest.java:
##########
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.rest.postman;
+
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.rest.postman.support.PostmanRequestBinding;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;

Review Comment:
   Nit: the other tests in camel-rest-postman use AssertJ only, so per the CLAUDE.md assertion rule this test should use `assertThat(...)` instead of JUnit `assertEquals`.



-- 
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-25306: camel-rest-openapi, camel-rest-postman - Decode the path parameters of contract-first operations [camel]

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


##########
components/camel-rest-postman/src/test/java/org/apache/camel/component/rest/postman/RestPostmanPathParameterDecodingTest.java:
##########
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.rest.postman;
+
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.rest.postman.support.PostmanRequestBinding;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;

Review Comment:
   Thanks @davsclaus, done in be861aea0c1d: the test now uses AssertJ `assertThat(...).isEqualTo(...)`. camel-rest-postman: 173 tests, 0 failures (camel-http-base: 51, 0 failures).
   
   _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-25306: camel-rest-openapi, camel-rest-postman - Decode the path parameters of contract-first operations [camel]

Posted by "allthingssecurity (via GitHub)" <gi...@apache.org>.
allthingssecurity commented on PR #27469:
URL: https://github.com/apache/camel/pull/27469#issuecomment-6035269218

   @oscerd CI has now reported and is green on this branch.
   
   _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-25306: camel-rest-openapi, camel-rest-postman - Decode the path parameters of contract-first operations [camel]

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

   <!-- ci-tested-modules -->
   :test_tube: **CI tested the following changed modules:**
   
   - `components/camel-http-base`
   - `components/camel-rest-openapi`
   - `components/camel-rest-postman`
   - `docs`
   
   > :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: 81 of 699 tested, 26 compile-only β€” current: 81 all tested</summary>
   
   [Maveniverse Scalpel](https://github.com/maveniverse/scalpel) detected **81 affected modules** (current approach: 81).
   
   **Skip-tests mode would test 81 modules** (4 direct + 78 downstream), **skip tests for 26** (generated code, meta-modules)
   
   <details><summary>Modules Scalpel would test (81)</summary>
   
   - `camel-a2a` ← downstream of org.apache.camel:camel-vertx-http
   - `camel-ai-observability` ← downstream of org.apache.camel:camel-telemetry
   - `camel-as2` ← downstream of org.apache.camel:camel-jetty
   - `camel-atmosphere-websocket` ← downstream of org.apache.camel:camel-servlet
   - `camel-clickup` ← downstream of org.apache.camel:camel-netty-http
   - `camel-consul` ← downstream of org.apache.camel:camel-undertow
   - `camel-cxf-common` ← downstream of org.apache.camel:camel-http-base
   - `camel-cxf-rest` ← downstream of org.apache.camel:camel-http-base
   - `camel-cxf-soap` ← downstream of org.apache.camel:camel-http-base
   - `camel-cxf-spring-common` ← downstream of org.apache.camel:camel-http-base
   - `camel-cxf-spring-rest` ← downstream of org.apache.camel:camel-undertow
   - `camel-cxf-spring-soap` ← downstream of org.apache.camel:camel-undertow
   - `camel-cxf-spring-transport` ← downstream of org.apache.camel:camel-cxf-spring-common
   - `camel-cxf-transport` ← downstream of org.apache.camel:camel-http-common
   - `camel-graphql` ← downstream of org.apache.camel:camel-http-base
   - `camel-http` ← downstream of org.apache.camel:camel-http-common
   - `camel-http-base` ← components/camel-http-base/src/main/java/org/apache/camel/http/base/HttpHelper.java, components/camel-http-base/src/test/java/org/apache/camel/http/base/HttpHelperTest.java
   - `camel-http-common` ← downstream of org.apache.camel:camel-http-base
   - `camel-java-joor-dsl` ← downstream of org.apache.camel:camel-telegram
   - `camel-jbang-mcp` ← downstream of org.apache.camel:camel-yaml-dsl
   - `camel-jbang-plugin-mcp` ← downstream of org.apache.camel:camel-jbang-core
   - `camel-jbang-plugin-route-parser` ← downstream of org.apache.camel:camel-route-parser
   - `camel-jbang-plugin-tui` ← downstream of org.apache.camel:camel-catalog
   - `camel-jbang-plugin-validate` ← downstream of org.apache.camel:camel-yaml-dsl-validator
   - `camel-jetty` ← downstream of org.apache.camel:camel-http-common
   - `camel-jetty-common` ← downstream of org.apache.camel:camel-http-common
   - `camel-jsonpath` ← downstream of org.apache.camel:camel-platform-http-vertx
   - `camel-kamelet` ← downstream of org.apache.camel:camel-http
   - `camel-knative-http` ← downstream of org.apache.camel:camel-platform-http-vertx
   - `camel-kubernetes` ← downstream of org.apache.camel:camel-http
   - `camel-langchain4j-agent` ← downstream of org.apache.camel:camel-telemetry
   - `camel-langchain4j-chat` ← downstream of org.apache.camel:camel-telemetry
   - `camel-langchain4j-embeddings` ← downstream of org.apache.camel:camel-telemetry
   - `camel-langchain4j-embeddingstore` ← downstream of org.apache.camel:camel-langchain4j-embeddings
   - `camel-launcher-container` ← downstream of org.apache.camel:camel-launcher
   - `camel-lra` ← downstream of org.apache.camel:camel-undertow
   - `camel-mcp-server` ← downstream of org.apache.camel:camel-platform-http-vertx
   - `camel-micrometer-observability` ← downstream of org.apache.camel:camel-undertow
   - `camel-micrometer-prometheus` ← downstream of org.apache.camel:camel-platform-http-main
   - `camel-netty-http` ← downstream of org.apache.camel:camel-http-base
   - `camel-oauth` ← downstream of org.apache.camel:camel-vertx-http
   - `camel-observability-services` ← downstream of org.apache.camel:camel-opentelemetry2
   - `camel-odata` ← downstream of org.apache.camel:camel-http-base
   - `camel-openai` ← downstream of org.apache.camel:camel-platform-http-vertx
   - `camel-openapi-validator` ← downstream of org.apache.camel:camel-http-base
   - `camel-opentelemetry` ← downstream of org.apache.camel:camel-undertow
   - `camel-opentelemetry2` ← downstream of org.apache.camel:camel-undertow
   - `camel-platform-http` ← downstream of org.apache.camel:camel-http-base
   - `camel-platform-http-jolokia` ← downstream of org.apache.camel:camel-platform-http
   - `camel-platform-http-main` ← downstream of org.apache.camel:camel-platform-http-vertx
   - `camel-platform-http-vertx` ← downstream of org.apache.camel:camel-http-base
   - `camel-quickfix` ← downstream of org.apache.camel:camel-jetty
   - `camel-rest-openapi` ← components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java, components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiPathParameterDecodingTest.java, components/camel-rest-openapi/src/test/resources/path-parameters.yaml
   - `camel-rest-postman` ← components/camel-rest-postman/src/main/java/org/apache/camel/component/rest/postman/RestPostmanProcessor.java, components/camel-rest-postman/src/test/java/org/apache/camel/component/rest/postman/RestPostmanPathParameterDecodingTest.java
   - `camel-restdsl-openapi-plugin` ← downstream of org.apache.camel:camel-platform-http
   - `camel-sap-netweaver` ← downstream of org.apache.camel:camel-http
   - `camel-semantic` ← downstream of org.apache.camel:camel-xml-io-dsl
   - `camel-servlet` ← downstream of org.apache.camel:camel-http-common
   - `camel-slack` ← downstream of org.apache.camel:camel-undertow
   - `camel-soap` ← downstream of org.apache.camel:camel-cxf-soap
   - `camel-spring-ai-chat` ← downstream of org.apache.camel:camel-telemetry
   - `camel-spring-rabbitmq` ← downstream of org.apache.camel:camel-http
   - `camel-state-store` ← downstream of org.apache.camel:camel-test-main-junit5
   - `camel-telegram` ← downstream of org.apache.camel:camel-netty-http
   - `camel-telemetry` ← downstream of org.apache.camel:camel-undertow
   - `camel-telemetry-dev` ← downstream of org.apache.camel:camel-undertow
   - `camel-test-main-junit5` ← downstream of org.apache.camel:camel-xml-io-dsl
   - `camel-test-main-junit6` ← downstream of org.apache.camel:camel-xml-io-dsl
   - `camel-typesafe-ai` ← downstream of org.apache.camel:camel-xml-io-dsl
   - `camel-undertow` ← downstream of org.apache.camel:camel-http-base
   - `camel-undertow-spring-security` ← downstream of org.apache.camel:camel-undertow
   - `camel-vertx-http` ← downstream of org.apache.camel:camel-http-base
   - `camel-webhook` ← downstream of org.apache.camel:camel-netty-http
   - `camel-whatsapp` ← downstream of org.apache.camel:camel-netty-http
   - `camel-xml-io-dsl` ← downstream of org.apache.camel:camel-telegram
   - `camel-xml-jaxb-dsl` ← downstream of org.apache.camel:camel-telegram
   - `camel-xml-jaxb-dsl-test-definition` ← downstream of org.apache.camel:camel-telegram
   - `camel-xml-jaxb-dsl-test-spring` ← downstream of org.apache.camel:camel-telegram
   - `camel-yaml-dsl-validator` ← downstream of org.apache.camel:camel-yaml-dsl
   - `camel-yaml-dsl-validator-maven-plugin` ← downstream of org.apache.camel:camel-yaml-dsl-validator
   - `camel-zookeeper` ← downstream of org.apache.camel:camel-undertow
   
   </details>
   
   <details><summary>Modules with tests skipped (26)</summary>
   
   - `apache-camel`
   - `camel-allcomponents`
   - `camel-catalog`
   - `camel-catalog-console`
   - `camel-catalog-maven`
   - `camel-catalog-suggest`
   - `camel-componentdsl`
   - `camel-endpointdsl`
   - `camel-endpointdsl-support`
   - `camel-itest`
   - `camel-jbang-core`
   - `camel-jbang-it`
   - `camel-jbang-main`
   - `camel-jbang-plugin-edit`
   - `camel-jbang-plugin-generate`
   - `camel-jbang-plugin-kubernetes`
   - `camel-jbang-plugin-test`
   - `camel-kamelet-main`
   - `camel-launcher`
   - `camel-report-maven-plugin`
   - `camel-route-parser`
   - `camel-yaml-dsl`
   - `camel-yaml-dsl-deserializers`
   - `camel-yaml-dsl-maven-plugin`
   - `coverage`
   - `dummy-component`
   
   </details>
   
   > :information_source: Shadow mode β€” Scalpel observes but does not affect test execution. [Learn more](https://github.com/maveniverse/scalpel)
   
   </details>
   
   <details><summary>Build reactor β€” dependencies compiled but only changed modules were tested (4 modules, 1m 0s total)</summary>
   
   **Total reactor time:** 1m 0s
   
   | Module | Duration | Status |
   | --- | --- | --- |
   | Camel :: REST OpenApi | 24.9s | SUCCESS |
   | Camel :: REST Postman | 14.4s | SUCCESS |
   | Camel :: Docs | 13.2s | SUCCESS |
   | Camel :: HTTP :: Base | 7.6s | SUCCESS |
   
   **Top 20 slowest modules:**
   - `Camel :: REST OpenApi` (24.9s)
   - `Camel :: REST Postman` (14.4s)
   - `Camel :: Docs` (13.2s)
   - `Camel :: HTTP :: Base` (7.6s)
   
   </details>
   
   ---
   :gear: [View full build and test results](https://github.com/apache/camel/actions/runs/37550204441)


-- 
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-25306: camel-rest-openapi, camel-rest-postman - Decode the path parameters of contract-first operations [camel]

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


-- 
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-25306: camel-rest-openapi, camel-rest-postman - Decode the path parameters of contract-first operations [camel]

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

   :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