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

   # Description
   
   A header sent more than once arrives on the message as a Collection 
(CollectionHelper.appendEntry). The request adapter converted it with 
getHeader(key, String.class), which ends in ToStringTypeConverter and yields 
the collection's toString() - "[a, b]" - so the validator checked the schema 
against a value the client never sent.
   
   Two consequences. A repeated scalar parameter is never reported, because the 
fabricated string is still a string and satisfies "type": "string". And for a 
parameter with a pattern, enum, format or maxLength the check runs against the 
wrong value, which can reject a request while naming something the client did 
not send, or accept one it should not.
   
   Query parameters in the same method are already handed over one per 
occurrence, which is why a repeated query parameter is reported correctly today 
and a repeated header is not. SimpleRequest.Builder.withHeader(String, List) 
exists; this passes the values on rather than flattening them.
   
   Tests: a repeated scalar header (api_key) is now reported, including when 
the client spells it differently (Api_Key) since header names are 
case-insensitive and so is Camel's header map; a single value still passes; a 
repeated array header (tags) is reported for the reason the specification gives 
- a header array is serialized as one comma-separated value, style "simple" 
with explode=false - and that correct form still passes. The three "must be 
reported" tests fail without the change.
   
   ## What is wrong
   
   `OpenApiRestClientRequestValidator` builds the `SimpleRequest` it hands to 
swagger-request-validator. For headers it does:
   
   ```java
   builder.withHeader(key, exchange.getMessage().getHeader(key, String.class));
   ```
   
   A header sent more than once arrives on the message as a `Collection` — 
`CollectionHelper.appendEntry` turns the second occurrence into a `List`. 
Converting that to `String` falls through to `ToStringTypeConverter`, which 
returns `value.toString()`. The validator therefore receives
   
   ```
   api_key: [key-one, key-two]
   ```
   
   a value that was never on the wire.
   
   ### Why this is a correctness problem, not only a missing check
   
   1. A repeated **scalar** parameter is never reported. The fabricated string 
is still a string, so a `"type": "string"` header accepts it and the request 
passes.
   2. For a parameter with `pattern`, `enum`, `format` or `maxLength` the 
schema is checked against the wrong value. That can reject a request while 
naming something the client did not send, or accept one it should not.
   
   ### Asymmetry in the same method
   
   Query parameters a few lines below are handed over **once per occurrence**:
   
   ```java
   String[] params = query.split("&");
   for (String param : params) {
       ...
       builder.withQueryParam(qKey, qValue);
   }
   ```
   
   which is why `?status=a&status=b` is reported correctly today while the 
equivalent header is not. `SimpleRequest.Builder` has `withHeader(String, 
List<String>)` and `withHeader(String, String...)`; the adapter simply does not 
use them.
   
   ## Steps to reproduce
   
   With the petstore contract already in
   `components/camel-openapi-validator/src/test/resources/petstore-v3.json`
   (`DELETE /pet/{petId}` declares the header `api_key` as `"type": "string"`):
   
   ```java
   exchange.getMessage().setHeader(Exchange.HTTP_METHOD, "DELETE");
   exchange.getMessage().setHeader(Exchange.HTTP_PATH, "pet/123");
   exchange.getMessage().setHeader("api_key", List.of("key-one", "key-two"));
   ```
   
   Expected: a validation error. Actual: `null`, and the validator saw
   `api_key: [key-one, key-two]`.
   
   ## Proposed fix
   
   Pass the values on when the header is a `Collection`, converting each 
element individually, and keep the single-value path unchanged.
   
   ## Behaviour change to be aware of
   
   A deployment whose contract declares a scalar header and whose clients 
repeat it currently gets `200` and will get a validation error after this 
change. That is the point of the fix, but it is a visible change.
   
   A header declared `"type": "array"` is reported too when it is repeated, 
with `Parameter 'tags' expected an array style of 'simple' [explode=false].` 
That is correct per the OpenAPI specification: a header array is serialized as 
one header with a comma-separated value, not by repeating the header. The 
correct form (`tags: dog,cat`) is unaffected, and there is a test for it.
   
   ## Tests
   
   `OpenApiRestClientRequestValidatorTest` gains four cases:
   
   | Test | Asserts |
   |---|---|
   | `testValidateRepeatedScalarHeader` | a repeated `api_key` is reported, and 
the collection is not stringified into the message |
   | `testValidateRepeatedScalarHeaderInMixedCase` | `Api_Key` is checked too — 
header names are case-insensitive, and so is Camel's header map |
   | `testValidateSingleScalarHeaderStillPasses` | no regression on the 
single-value path |
   | `testValidateRepeatedArrayHeaderIsReported` | a repeated `tags` is 
reported with the style message |
   | `testValidateArrayHeaderInSimpleStyleStillPasses` | `tags: dog,cat` stays 
valid |
   
   The three "must be reported" tests fail without the change. `mvn clean 
install -Psourcecheck` in `components/camel-openapi-validator` is green: 15 
tests.
   
   # Target
   
   - [x] I checked that the commit is targeting the correct branch (Camel 4 
uses the `main` branch)
   
   # Tracking
   - [ ] 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).
   
   <!--
   # *Note*: trivial changes like, typos, minor documentation fixes and other 
small items do not require a JIRA issue. In this case your pull request should 
address just this issue, without pulling in other changes.
   -->
   
   # Apache Camel coding standards and style
   
   - [x] I checked that each commit in the pull request has a meaningful 
subject line and body.
   
   <!--
   If you're unsure, you can format the pull request title like `[CAMEL-XXX] 
Fixes bug in camel-file component`, where you replace `CAMEL-XXX` with the 
appropriate JIRA issue.
   -->
   
   - [ ] I have run `mvn clean install -DskipTests` locally from root folder 
and I have committed all auto-generated changes.
   
   <!--
   You can run the aforementioned command in your module so that the build 
auto-formats your code. This will also be verified as part of the checks and 
your PR may be rejected if if there are uncommited changes after running `mvn 
clean install -DskipTests`.
   
   You can learn more about the contribution guidelines at 
https://github.com/apache/camel/blob/main/CONTRIBUTING.md
   -->
   
   # 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.
   
   # Target
   
   - [x] I checked that the commit is targeting the correct branch (Camel 4 
uses the `main` branch)
   
   # Tracking
   - [ ] 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).
   
   <!--
   # *Note*: trivial changes like, typos, minor documentation fixes and other 
small items do not require a JIRA issue. In this case your pull request should 
address just this issue, without pulling in other changes.
   -->
   
   # Apache Camel coding standards and style
   
   - [x] I checked that each commit in the pull request has a meaningful 
subject line and body.
   
   <!--
   If you're unsure, you can format the pull request title like `[CAMEL-XXX] 
Fixes bug in camel-file component`, where you replace `CAMEL-XXX` with the 
appropriate JIRA issue.
   -->
   
   - [ ] I have run `mvn clean install -DskipTests` locally from root folder 
and I have committed all auto-generated changes.
   
   <!--
   You can run the aforementioned command in your module so that the build 
auto-formats your code. This will also be verified as part of the checks and 
your PR may be rejected if if there are uncommited changes after running `mvn 
clean install -DskipTests`.
   
   You can learn more about the contribution guidelines at 
https://github.com/apache/camel/blob/main/CONTRIBUTING.md
   -->
   
   # 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 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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to