This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch camel-3.7.x in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-3.7.x by this push: new 47c0dc4 [CAMEL-16699] Fix HttpProducer bridged endpoint skipRequestHeaders for common type headers (#5655) 47c0dc4 is described below commit 47c0dc45266e6c1a907893349b5a48e1542b9976 Author: Mathias Teikari <m47i...@gmail.com> AuthorDate: Fri Jun 11 12:28:28 2021 +0200 [CAMEL-16699] Fix HttpProducer bridged endpoint skipRequestHeaders for common type headers (#5655) * Add unit test for CAMEL-16699: HttpProducer skip request headers for query params on bridge endpoint broken for common types * CAMEL-16699: HttpProducer skip request headers for query params on bridge endpoint broken for common types Cherry pick commit 031ea4b4 applied to camel-3.7.x branch. * Upcase constant name to adhere to style guide. --- .../apache/camel/component/http/HttpProducer.java | 12 +- .../http/HttpProducerBridgeEndpointTest.java | 143 +++++++++++++++++++++ .../http/handler/HeaderValidationHandler.java | 23 ++++ 3 files changed, 171 insertions(+), 7 deletions(-) diff --git a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java index 1923822..ac8285b 100644 --- a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java +++ b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java @@ -134,10 +134,14 @@ public class HttpProducer extends DefaultProducer { final TypeConverter tc = exchange.getContext().getTypeConverter(); for (Map.Entry<String, Object> entry : in.getHeaders().entrySet()) { String key = entry.getKey(); + // we should not add headers for the parameters in the uri if we bridge the endpoint + // as then we would duplicate headers on both the endpoint uri, and in HTTP headers as well + if (skipRequestHeaders != null && skipRequestHeaders.containsKey(key)) { + continue; + } Object headerValue = entry.getValue(); if (headerValue != null) { - if (headerValue instanceof String) { // optimise for string values String value = (String) headerValue; @@ -166,12 +170,6 @@ public class HttpProducer extends DefaultProducer { // should be combined into a single value while (it.hasNext()) { String value = tc.convertTo(String.class, it.next()); - - // we should not add headers for the parameters in the uri if we bridge the endpoint - // as then we would duplicate headers on both the endpoint uri, and in HTTP headers as well - if (skipRequestHeaders != null && skipRequestHeaders.containsKey(key)) { - continue; - } if (value != null && !strategy.applyFilterToCamelHeaders(key, value, exchange)) { if (prev == null) { prev = value; diff --git a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpProducerBridgeEndpointTest.java b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpProducerBridgeEndpointTest.java new file mode 100644 index 0000000..f1f3ed7 --- /dev/null +++ b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpProducerBridgeEndpointTest.java @@ -0,0 +1,143 @@ +/* + * 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.http; + +import java.time.Instant; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.Exchange; +import org.apache.camel.component.http.handler.HeaderValidationHandler; +import org.apache.http.impl.bootstrap.HttpServer; +import org.apache.http.impl.bootstrap.ServerBootstrap; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class HttpProducerBridgeEndpointTest extends BaseHttpTest { + + private static final Instant INSTANT = Instant.parse("2021-06-10T14:42:00Z"); + private static final String STRING = "text"; + private static final Integer INTEGER = Integer.valueOf(1); + private static final Long LONG = Long.valueOf(999999999999999L); + private static final Boolean BOOLEAN = true; + private static final String QUERY + = "qp1=" + INSTANT + "&qp2=" + STRING + "&qp3=" + INTEGER + "&qp4=" + LONG + "&qp5=" + BOOLEAN; + + private HttpServer localServer; + + @BeforeEach + @Override + public void setUp() throws Exception { + String[] absentHeaders = new String[] { "qp1", "qp2", "qp3", "qp4", "qp5" }; + Map<String, String> noBridgeExpectedHeaders = new HashMap<>(); + noBridgeExpectedHeaders.put("qp1", INSTANT.toString()); + noBridgeExpectedHeaders.put("qp2", STRING); + noBridgeExpectedHeaders.put("qp3", INTEGER.toString()); + noBridgeExpectedHeaders.put("qp4", LONG.toString()); + noBridgeExpectedHeaders.put("qp5", BOOLEAN.toString()); + + localServer = ServerBootstrap.bootstrap().setHttpProcessor(getBasicHttpProcessor()) + .setConnectionReuseStrategy(getConnectionReuseStrategy()).setResponseFactory(getHttpResponseFactory()) + .setExpectationVerifier(getHttpExpectationVerifier()).setSslContext(getSSLContext()) + .registerHandler("/bridged", + new HeaderValidationHandler( + "GET", + QUERY, + null, + getExpectedContent(), + null, + Arrays.asList(absentHeaders))) + .registerHandler("/notbridged", + new HeaderValidationHandler( + "GET", + QUERY, + null, + getExpectedContent(), + noBridgeExpectedHeaders)) + .create(); + + localServer.start(); + + super.setUp(); + } + + @AfterEach + @Override + public void tearDown() throws Exception { + super.tearDown(); + + if (localServer != null) { + localServer.stop(); + } + } + + @Test + public void testHttpProducerBridgeEndpointSkipRequestHeaders() throws Exception { + + HttpComponent component = context.getComponent("http", HttpComponent.class); + component.setConnectionTimeToLive(1000L); + + HttpEndpoint endpoint = (HttpEndpoint) component + .createEndpoint("http://" + localServer.getInetAddress().getHostName() + ":" + + localServer.getLocalPort() + "/bridged?bridgeEndpoint=true"); + HttpProducer producer = new HttpProducer(endpoint); + + Exchange exchange = producer.createExchange(); + exchange.getIn().setBody(null); + exchange.getIn().setHeader(Exchange.HTTP_QUERY, QUERY); + exchange.getIn().setHeader("qp1", INSTANT); + exchange.getIn().setHeader("qp2", STRING); + exchange.getIn().setHeader("qp3", INTEGER); + exchange.getIn().setHeader("qp4", LONG); + exchange.getIn().setHeader("qp5", BOOLEAN); + + producer.start(); + producer.process(exchange); + producer.stop(); + + assertExchange(exchange); + } + + @Test + public void testHttpProducerNoBridgeEndpointRequestHeaders() throws Exception { + + HttpComponent component = context.getComponent("http", HttpComponent.class); + component.setConnectionTimeToLive(1000L); + + HttpEndpoint endpoint = (HttpEndpoint) component + .createEndpoint("http://" + localServer.getInetAddress().getHostName() + ":" + + localServer.getLocalPort() + "/notbridged"); + HttpProducer producer = new HttpProducer(endpoint); + + Exchange exchange = producer.createExchange(); + exchange.getIn().setBody(null); + exchange.getIn().setHeader(Exchange.HTTP_QUERY, QUERY); + exchange.getIn().setHeader("qp1", INSTANT); + exchange.getIn().setHeader("qp2", STRING); + exchange.getIn().setHeader("qp3", INTEGER); + exchange.getIn().setHeader("qp4", LONG); + exchange.getIn().setHeader("qp5", BOOLEAN); + + producer.start(); + producer.process(exchange); + producer.stop(); + + assertExchange(exchange); + } +} diff --git a/components/camel-http/src/test/java/org/apache/camel/component/http/handler/HeaderValidationHandler.java b/components/camel-http/src/test/java/org/apache/camel/component/http/handler/HeaderValidationHandler.java index d9c8be7..240e56b 100644 --- a/components/camel-http/src/test/java/org/apache/camel/component/http/handler/HeaderValidationHandler.java +++ b/components/camel-http/src/test/java/org/apache/camel/component/http/handler/HeaderValidationHandler.java @@ -17,6 +17,7 @@ package org.apache.camel.component.http.handler; import java.io.IOException; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -29,7 +30,12 @@ import org.apache.http.protocol.HttpContext; public class HeaderValidationHandler extends BasicValidationHandler { + // Map of headers and values that are expected to be present + // in HttpRequest. protected Map<String, String> expectedHeaders; + // List of headers that are expected to be absent from HttpRequest + // (e.g. for testing filtering). + protected List<String> absentHeaders; public HeaderValidationHandler(String expectedMethod, String expectedQuery, Object expectedContent, String responseContent, @@ -38,6 +44,14 @@ public class HeaderValidationHandler extends BasicValidationHandler { this.expectedHeaders = expectedHeaders; } + public HeaderValidationHandler(String expectedMethod, String expectedQuery, + Object expectedContent, String responseContent, + Map<String, String> expectedHeaders, + List<String> absentHeaders) { + this(expectedMethod, expectedQuery, expectedContent, responseContent, expectedHeaders); + this.absentHeaders = absentHeaders; + } + @Override public void handle( final HttpRequest request, final HttpResponse response, @@ -63,6 +77,15 @@ public class HeaderValidationHandler extends BasicValidationHandler { } } + if (absentHeaders != null) { + for (String header : absentHeaders) { + if (request.getHeaders(header).length > 0) { + response.setStatusCode(HttpStatus.SC_EXPECTATION_FAILED); + return; + } + } + } + super.handle(request, response, context); }