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]