davsclaus commented on code in PR #27099:
URL: https://github.com/apache/camel/pull/27099#discussion_r4136334761
##########
components/camel-openapi-validator/src/main/java/org/apache/camel/component/rest/openapi/validator/client/OpenApiRestClientRequestValidator.java:
##########
@@ -104,7 +107,21 @@ public ValidationError validate(Exchange exchange,
ValidationContext validationC
boolean customHeader
= !startsWithIgnoreCase(key, "Camel") &&
!filter.applyFilterToCamelHeaders(key, value, exchange);
if (customHeader) {
- builder.withHeader(key, exchange.getMessage().getHeader(key,
String.class));
+ if (value instanceof Collection<?> values) {
+ // A header sent more than once arrives as a Collection
(CollectionHelper.appendEntry).
+ // Converting that to a single String would hand the
validator the collection's
+ // toString(), such as "[a, b]" - a value the client never
sent - so the schema would
+ // be checked against fabricated data, and a repeated
scalar parameter would never be
+ // reported. Pass the values on instead, as the query
parameters below already do.
+ List<String> headerValues = new ArrayList<>(values.size());
+ for (Object headerValue : values) {
+
headerValues.add(exchange.getContext().getTypeConverter()
+ .convertTo(String.class, exchange,
headerValue));
+ }
+ builder.withHeader(key, headerValues);
Review Comment:
Per RFC 9110 ยง5.3, repeating a list-valued header is equivalent to one
header with the values joined by commas. So `tags: dog` + `tags: cat` means the
same as `tags: dog,cat`, which the contract accepts. With this change the
repeated form is rejected: the `[explode=false]` in that message is hardcoded
in swagger-request-validator's `ParameterValidator`, and the petstore contract
declares `explode: true`. Could we join the values with `,` when the header
parameter is an array schema, and keep the list for scalars (where >1 value
really is invalid)? Also, `convertTo` can return null for a null element; worth
skipping those.
##########
components/camel-openapi-validator/src/test/java/org/apache/camel/component/rest/openapi/validator/client/OpenApiRestClientRequestValidatorTest.java:
##########
@@ -123,4 +124,104 @@ public void testValidateHeader() {
"application/json", "application/json", true, null, null,
null, null));
Assertions.assertNull(error);
}
+
+ @Test
+ public void testValidateRepeatedScalarHeader() {
+ exchange.setProperty(Exchange.REST_OPENAPI, openAPI);
+ exchange.setProperty(Exchange.CONTENT_TYPE, "application/json");
+ exchange.getMessage().setHeader(Exchange.HTTP_METHOD, "DELETE");
+ exchange.getMessage().setHeader(Exchange.HTTP_PATH, "pet/123");
+ exchange.getMessage().setHeader("Accept", "application/json");
+ exchange.getMessage().setBody("");
+
+ // A header sent more than once arrives as a List, exactly as
CollectionHelper.appendEntry
+ // leaves it. api_key is declared "type": "string", so two values
violate the contract.
+ exchange.getMessage().setHeader("api_key", List.of("key-one",
"key-two"));
+
+ RestClientRequestValidator.ValidationError error
+ = validator.validate(exchange, new
RestClientRequestValidator.ValidationContext(
+ "application/json", "application/json", false, null,
null, null, null));
+
+ Assertions.assertNotNull(error, "a repeated scalar header parameter
must be reported");
+ Assertions.assertEquals(400, error.statusCode());
+ Assertions.assertFalse(error.body().contains("[key-one, key-two]"),
+ "the collection must not be stringified into the validated
value");
+ }
+
+ @Test
+ public void testValidateSingleScalarHeaderStillPasses() {
+ exchange.setProperty(Exchange.REST_OPENAPI, openAPI);
+ exchange.setProperty(Exchange.CONTENT_TYPE, "application/json");
+ exchange.getMessage().setHeader(Exchange.HTTP_METHOD, "DELETE");
+ exchange.getMessage().setHeader(Exchange.HTTP_PATH, "pet/123");
+ exchange.getMessage().setHeader("Accept", "application/json");
+ exchange.getMessage().setHeader("api_key", "key-one");
+ exchange.getMessage().setBody("");
+
+ RestClientRequestValidator.ValidationError error
+ = validator.validate(exchange, new
RestClientRequestValidator.ValidationContext(
+ "application/json", "application/json", false, null,
null, null, null));
+
+ Assertions.assertNull(error);
+ }
+
+ @Test
+ public void testValidateRepeatedArrayHeaderIsReported() {
Review Comment:
This locks in rejecting a request that is valid HTTP (see the comment on the
validator). I'd drop it or flip it, depending on the outcome there.
--
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]