You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by or...@apache.org on 2022/05/31 12:04:59 UTC
[camel] branch main updated: CAMEL-17949 - Infinite loop when setting retries
This is an automated email from the ASF dual-hosted git repository.
orpiske pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 5d642dc6b07 CAMEL-17949 - Infinite loop when setting retries
5d642dc6b07 is described below
commit 5d642dc6b0749678c16b50586a1e82816554c34f
Author: Rhuan Rocha <rh...@gmail.com>
AuthorDate: Sun May 29 20:46:07 2022 -0300
CAMEL-17949 - Infinite loop when setting retries
Signed-off-by: Rhuan Rocha <rh...@gmail.com>
---
.../netty/http/DefaultNettyHttpBinding.java | 16 ++++
.../component/netty/http/NettyHttpProducer.java | 22 +++++-
.../netty/http/NettyHttpLoopErrorTest.java | 87 ++++++++++++++++++++++
3 files changed, 124 insertions(+), 1 deletion(-)
diff --git a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultNettyHttpBinding.java b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultNettyHttpBinding.java
index b536ed23336..f3785da9199 100644
--- a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultNettyHttpBinding.java
+++ b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultNettyHttpBinding.java
@@ -285,6 +285,20 @@ public class DefaultNettyHttpBinding implements NettyHttpBinding, Cloneable {
}
+ /**
+ * Copy camel header from exchange to headers map.
+ *
+ * @param headers the map headers
+ * @param exchange the exchange
+ */
+ protected void copyCamelHeaders(Map<String, Object> headers, Exchange exchange) {
+ exchange.getIn().getHeaders().keySet()
+ .stream()
+ .filter(key -> key.startsWith("Camel"))
+ .forEach(key -> headers.put(key, exchange.getIn().getHeaders().get(key)));
+
+ }
+
/**
* Decodes the header if needed to, or returns the header value as is.
*
@@ -356,6 +370,8 @@ public class DefaultNettyHttpBinding implements NettyHttpBinding, Cloneable {
HttpResponse response, Map<String, Object> headers, Exchange exchange, NettyHttpConfiguration configuration) {
LOG.trace("populateCamelHeaders: {}", response);
+ copyCamelHeaders(headers, exchange);
+
headers.put(NettyHttpConstants.HTTP_RESPONSE_CODE, response.status().code());
headers.put(Exchange.HTTP_RESPONSE_TEXT, response.status().reasonPhrase());
diff --git a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/NettyHttpProducer.java b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/NettyHttpProducer.java
index e4f40352560..c96c0c73698 100644
--- a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/NettyHttpProducer.java
+++ b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/NettyHttpProducer.java
@@ -19,6 +19,7 @@ package org.apache.camel.component.netty.http;
import java.net.URI;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
@@ -169,7 +170,10 @@ public class NettyHttpProducer extends NettyProducer {
} else {
ok = NettyHttpHelper.isStatusCodeOk(code, configuration.getOkStatusCodeRange());
}
- if (!ok && getConfiguration().isThrowExceptionOnFailure()) {
+
+ if (ok) {
+ removeCamelHeaders(exchange);
+ } else if (getConfiguration().isThrowExceptionOnFailure()) {
// operation failed so populate exception to throw
Exception cause = NettyHttpHelper.populateNettyHttpOperationFailedException(exchange, actualUrl,
response, code, getConfiguration().isTransferException());
@@ -184,4 +188,20 @@ public class NettyHttpProducer extends NettyProducer {
}
}
}
+
+ /**
+ * Remove Camel headers from Out message
+ *
+ * @param exchange the exchange
+ */
+ protected void removeCamelHeaders(Exchange exchange) {
+ List<String> headersToRemove = exchange.getMessage().getHeaders().keySet()
+ .stream()
+ .filter(key -> !key.equalsIgnoreCase(Exchange.HTTP_RESPONSE_CODE)
+ && !key.equalsIgnoreCase(Exchange.HTTP_RESPONSE_TEXT)
+ && key.startsWith("Camel"))
+ .collect(Collectors.toList());
+
+ headersToRemove.stream().forEach(header -> exchange.getMessage().removeHeaders(header));
+ }
}
diff --git a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpLoopErrorTest.java b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpLoopErrorTest.java
new file mode 100644
index 00000000000..fc85b2879a6
--- /dev/null
+++ b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpLoopErrorTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.netty.http;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.direct.DirectEndpoint;
+import org.apache.camel.http.base.HttpOperationFailedException;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class NettyHttpLoopErrorTest extends BaseNettyTest {
+
+ @EndpointInject("direct:input")
+ DirectEndpoint directEndpoint;
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+
+ @Override
+ public void configure() throws Exception {
+ onException(NettyHttpOperationFailedException.class)
+ .maximumRedeliveries(2)
+ .retryAttemptedLogLevel(LoggingLevel.WARN)
+ .maximumRedeliveryDelay(1000)
+ .handled(false);
+
+ onException(HttpOperationFailedException.class)
+ .maximumRedeliveries(2)
+ .retryAttemptedLogLevel(LoggingLevel.WARN)
+ .maximumRedeliveryDelay(1000)
+ .handled(false);
+
+ from("direct:input")
+ .routeId("test-route")
+ .toD("${body}");
+ }
+ };
+ }
+
+ @Test
+ void testRetryWithExchangeInOnly() {
+ boolean isException = false;
+ try {
+ template.sendBody(directEndpoint, ExchangePattern.InOnly, "netty-http:http://example.com/return_404");
+ } catch (Exception e) {
+ isException = true;
+ }
+
+ assertTrue(isException);
+
+ }
+
+ @Test
+ void testRetryWithExchangeInOut() {
+
+ boolean isException = false;
+ try {
+ template.sendBody(directEndpoint, ExchangePattern.InOut, "netty-http:http://example.com/return_404");
+ } catch (Exception e) {
+ isException = true;
+ }
+
+ assertTrue(isException);
+
+ }
+
+}