You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/10/16 03:49:12 UTC
[camel] branch master updated: CAMEL-14029 Change HTTP Status code
to 204 when no content exists (Undertow) (#3239)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push:
new 2e63c0f CAMEL-14029 Change HTTP Status code to 204 when no content exists (Undertow) (#3239)
2e63c0f is described below
commit 2e63c0f4cf41fcc2d243eded2fe60099eaed6cb3
Author: Mike Barlotta <Co...@users.noreply.github.com>
AuthorDate: Tue Oct 15 23:48:52 2019 -0400
CAMEL-14029 Change HTTP Status code to 204 when no content exists (Undertow) (#3239)
* CAMEL-14029 Change HTTP Status code to 204 when no content exists
(Undertow)
* cleanup undertow code for 204 switch
* cleanup
* move code to check content based on PR comments
* remove unused imports
* remove extra line
* minor tweak
* revamp methods so has a single starting point
* update approach: no longer check body for specific values
* Moved all of status code setting into one method
* revamp method to determine and return the status code instead of
changing it
* remove commented out older method
* checksource = remove ()
---
.../undertow/DefaultUndertowHttpBinding.java | 48 +++++--
.../camel/component/undertow/UndertowConsumer.java | 10 +-
.../undertow/UndertowConsumerUnregisterTest.java | 29 ++--
.../undertow/UndertowSwitchingStatus204Test.java | 154 +++++++++++++++++++++
4 files changed, 209 insertions(+), 32 deletions(-)
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java
index 778e6a2..328a80c 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java
@@ -42,6 +42,8 @@ import io.undertow.util.HeaderMap;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;
import io.undertow.util.Methods;
+import io.undertow.util.StatusCodes;
+
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.TypeConverter;
@@ -319,16 +321,16 @@ public class DefaultUndertowHttpBinding implements UndertowHttpBinding {
@Override
public Object toHttpResponse(HttpServerExchange httpExchange, Message message) throws IOException {
- boolean failed = message.getExchange().isFailed();
- int defaultCode = failed ? 500 : 200;
-
- int code = message.getHeader(Exchange.HTTP_RESPONSE_CODE, defaultCode, int.class);
-
+ Exchange camelExchange = message.getExchange();
+ Object body = message.getBody();
+ Exception exception = camelExchange.getException();
+
+ int code = determineResponseCode(camelExchange, body);
+ message.getHeaders().put(Exchange.HTTP_RESPONSE_CODE, code);
httpExchange.setStatusCode(code);
- TypeConverter tc = message.getExchange().getContext().getTypeConverter();
-
//copy headers from Message to Response
+ TypeConverter tc = message.getExchange().getContext().getTypeConverter();
for (Map.Entry<String, Object> entry : message.getHeaders().entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
@@ -337,16 +339,13 @@ public class DefaultUndertowHttpBinding implements UndertowHttpBinding {
while (it.hasNext()) {
String headerValue = tc.convertTo(String.class, it.next());
if (headerValue != null && headerFilterStrategy != null
- && !headerFilterStrategy.applyFilterToCamelHeaders(key, headerValue, message.getExchange())) {
+ && !headerFilterStrategy.applyFilterToCamelHeaders(key, headerValue, camelExchange)) {
LOG.trace("HTTP-Header: {}={}", key, headerValue);
httpExchange.getResponseHeaders().add(new HttpString(key), headerValue);
}
}
}
- Object body = message.getBody();
- Exception exception = message.getExchange().getException();
-
if (exception != null && !isMuteException()) {
if (isTransferException()) {
// we failed due an exception, and transfer it as java serialized object
@@ -373,12 +372,12 @@ public class DefaultUndertowHttpBinding implements UndertowHttpBinding {
}
// and mark the exception as failure handled, as we handled it by returning it as the response
- ExchangeHelper.setFailureHandled(message.getExchange());
+ ExchangeHelper.setFailureHandled(camelExchange);
} else if (exception != null && isMuteException()) {
// mark the exception as failure handled, as we handled it by actively muting it
- ExchangeHelper.setFailureHandled(message.getExchange());
+ ExchangeHelper.setFailureHandled(camelExchange);
}
-
+
// set the content type in the response.
String contentType = MessageHelper.getContentType(message);
if (contentType != null) {
@@ -389,6 +388,27 @@ public class DefaultUndertowHttpBinding implements UndertowHttpBinding {
return body;
}
+ /*
+ * set the HTTP status code
+ */
+ private int determineResponseCode(Exchange camelExchange, Object body) {
+ boolean failed = camelExchange.isFailed();
+ int defaultCode = failed ? 500 : 200;
+
+ Message message = camelExchange.getMessage();
+ Integer currentCode = message.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
+ int codeToUse = currentCode == null ? defaultCode : currentCode;
+
+ if (codeToUse != 500) {
+ if ((body == null) || (body instanceof String && ((String) body).trim().isEmpty())) {
+ // no content
+ codeToUse = currentCode == null ? 204 : currentCode;
+ }
+ }
+
+ return codeToUse;
+ }
+
@Override
public Object toHttpRequest(ClientRequest clientRequest, Message message) {
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java
index 6e2d129..6ec1981 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java
@@ -202,7 +202,7 @@ public class UndertowConsumer extends DefaultConsumer implements HttpHandler {
httpExchange.getResponseSender().send(bodyAsByteBuffer);
}
}
-
+
/**
* Create an {@link Exchange} from the associated {@link UndertowEndpoint} and set the {@code in} {@link Message}'s
* body to the given {@code message} and {@link UndertowConstants#CONNECTION_KEY} header to the given
@@ -266,13 +266,7 @@ public class UndertowConsumer extends DefaultConsumer implements HttpHandler {
}
private Object getResponseBody(HttpServerExchange httpExchange, Exchange camelExchange) throws IOException {
- Object result;
- if (camelExchange.hasOut()) {
- result = getEndpoint().getUndertowHttpBinding().toHttpResponse(httpExchange, camelExchange.getOut());
- } else {
- result = getEndpoint().getUndertowHttpBinding().toHttpResponse(httpExchange, camelExchange.getIn());
- }
- return result;
+ return getEndpoint().getUndertowHttpBinding().toHttpResponse(httpExchange, camelExchange.getMessage());
}
private HttpHandler wrapHandler(HttpHandler handler, UndertowEndpoint endpoint) {
diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowConsumerUnregisterTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowConsumerUnregisterTest.java
index 4f8943f..cf1c46c 100644
--- a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowConsumerUnregisterTest.java
+++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowConsumerUnregisterTest.java
@@ -59,22 +59,24 @@ public class UndertowConsumerUnregisterTest extends BaseUndertowTest {
}
};
Exchange ret = template.request("undertow:http://localhost:{{port}}/foo", sender);
- Assert.assertEquals(200, ret.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
- Assert.assertEquals("test", ret.getOut().getBody(String.class));
+ Assert.assertEquals(200, ret.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE));
+ Assert.assertEquals("test", ret.getMessage().getBody(String.class));
+
ret = template.request("undertow:http://localhost:{{port}}/bar", sender);
- Assert.assertEquals(200, ret.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
- Assert.assertEquals("test", ret.getOut().getBody(String.class));
+ Assert.assertEquals(200, ret.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE));
+ Assert.assertEquals("test", ret.getMessage().getBody(String.class));
UndertowComponent component = context.getComponent("undertow", UndertowComponent.class);
UndertowConsumer consumerFoo = (UndertowConsumer) context.getRoute("route-foo").getConsumer();
component.unregisterEndpoint(consumerFoo.getEndpoint().getHttpHandlerRegistrationInfo(), consumerFoo.getEndpoint().getSslContext());
ret = template.request("undertow:http://localhost:{{port}}/foo", sender);
- Assert.assertEquals(404, ret.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
- Assert.assertEquals("No matching path found", ret.getOut().getBody(String.class));
+ Assert.assertEquals(404, ret.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE));
+ Assert.assertEquals("No matching path found", ret.getMessage().getBody(String.class));
+
ret = template.request("undertow:http://localhost:{{port}}/bar", sender);
- Assert.assertEquals(200, ret.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
- Assert.assertEquals("test", ret.getOut().getBody(String.class));
+ Assert.assertEquals(200, ret.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE));
+ Assert.assertEquals("test", ret.getMessage().getBody(String.class));
mockFoo.assertIsSatisfied();
mockBar.assertIsSatisfied();
@@ -84,8 +86,15 @@ public class UndertowConsumerUnregisterTest extends BaseUndertowTest {
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
public void configure() {
- from("undertow:http://localhost:{{port}}/foo").id("route-foo").to("mock:foo");
- from("undertow:http://localhost:{{port}}/bar").id("route-bar").to("mock:bar");
+ from("undertow:http://localhost:{{port}}/foo")
+ .id("route-foo")
+ .setBody().constant("test")
+ .to("mock:foo");
+
+ from("undertow:http://localhost:{{port}}/bar")
+ .id("route-bar")
+ .setBody().constant("test")
+ .to("mock:bar");
}
};
}
diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowSwitchingStatus204Test.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowSwitchingStatus204Test.java
new file mode 100644
index 0000000..a6f20e9
--- /dev/null
+++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowSwitchingStatus204Test.java
@@ -0,0 +1,154 @@
+/*
+ * 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.undertow;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+import org.junit.Test;
+
+public class UndertowSwitchingStatus204Test extends BaseUndertowTest {
+
+ @Test
+ public void testSwitchNoBodyTo204ViaHttpEmptyBody() throws Exception {
+ HttpUriRequest request = new HttpGet("http://localhost:" + getPort() + "/foo");
+ HttpClient httpClient = HttpClientBuilder.create().build();
+ HttpResponse httpResponse = httpClient.execute(request);
+
+ assertEquals(204, httpResponse.getStatusLine().getStatusCode());
+ assertNull(httpResponse.getEntity());
+ }
+
+ @Test
+ public void testSwitchingNoBodyTo204NettyHttpViaCamelEmptyBody() throws Exception {
+ Exchange inExchange = this.createExchangeWithBody("Hello World");
+ Exchange outExchange = template.send("undertow:http://localhost:{{port}}/foo", inExchange);
+
+ Message msg = outExchange.getMessage();
+ assertEquals(204, msg.getHeader(Exchange.HTTP_RESPONSE_CODE));
+ assertEquals("", msg.getBody(String.class));
+ }
+
+ @Test
+ public void testSwitchingNoBodyTo204ViaCamelRouteEmptyBody() throws Exception {
+ Exchange inExchange = this.createExchangeWithBody("Hello World");
+ Exchange outExchange = template.send("direct:foo", inExchange);
+
+ Message msg = outExchange.getMessage();
+ assertEquals(204, msg.getHeader(Exchange.HTTP_RESPONSE_CODE));
+ assertEquals("", msg.getBody(String.class));
+ }
+
+ @Test
+ public void testNoSwitchingHasBodyViaHttpNoContent() throws Exception {
+ HttpUriRequest request = new HttpGet("http://localhost:" + getPort() + "/bar");
+ HttpClient httpClient = HttpClientBuilder.create().build();
+ HttpResponse httpResponse = httpClient.execute(request);
+
+ assertEquals(200, httpResponse.getStatusLine().getStatusCode());
+ assertNotNull(httpResponse.getEntity());
+ assertEquals("No Content", EntityUtils.toString(httpResponse.getEntity()));
+ }
+
+ @Test
+ public void testNoSwitchingHasBodyNettyHttpViaCamelNoContent() throws Exception {
+ Exchange inExchange = this.createExchangeWithBody("Hello World");
+ Exchange outExchange = template.send("undertow:http://localhost:{{port}}/bar", inExchange);
+
+ Message msg = outExchange.getMessage();
+ assertEquals(200, msg.getHeader(Exchange.HTTP_RESPONSE_CODE));
+ assertEquals("No Content", msg.getBody(String.class));
+ }
+
+ @Test
+ public void testNoSwitchingHasBodyViaCamelRouteNoContent() throws Exception {
+ Exchange inExchange = this.createExchangeWithBody("Hello World");
+ Exchange outExchange = template.send("direct:bar", inExchange);
+
+ Message msg = outExchange.getMessage();
+ assertEquals(200, msg.getHeader(Exchange.HTTP_RESPONSE_CODE));
+ assertEquals("No Content", msg.getBody(String.class));
+ }
+
+ @Test
+ public void testNoSwitchingHasCodeViaHttpNoContent() throws Exception {
+ HttpUriRequest request = new HttpGet("http://localhost:" + getPort() + "/foobar");
+ HttpClient httpClient = HttpClientBuilder.create().build();
+ HttpResponse httpResponse = httpClient.execute(request);
+
+ assertEquals(200, httpResponse.getStatusLine().getStatusCode());
+ assertNotNull(httpResponse.getEntity());
+ assertEquals("", EntityUtils.toString(httpResponse.getEntity()));
+ }
+
+ @Test
+ public void testNoSwitchingHasCodeNettyHttpViaCamelNoContent() throws Exception {
+ Exchange inExchange = this.createExchangeWithBody("Hello World");
+ Exchange outExchange = template.send("undertow:http://localhost:{{port}}/foobar", inExchange);
+
+ Message msg = outExchange.getMessage();
+ assertEquals(200, msg.getHeader(Exchange.HTTP_RESPONSE_CODE));
+ assertEquals("", msg.getBody(String.class));
+ }
+
+ @Test
+ public void testNoSwitchingHasCodeViaCamelRouteNoContent() throws Exception {
+ Exchange inExchange = this.createExchangeWithBody("Hello World");
+ Exchange outExchange = template.send("direct:foobar", inExchange);
+
+ Message msg = outExchange.getMessage();
+ assertEquals(200, msg.getHeader(Exchange.HTTP_RESPONSE_CODE));
+ assertEquals("", msg.getBody(String.class));
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
+ from("undertow:http://localhost:{{port}}/foo")
+ .setBody().constant("");
+
+ from("direct:foo")
+ .to("undertow:http://localhost:{{port}}/foo");
+
+
+ from("undertow:http://localhost:{{port}}/bar")
+ .setBody().constant("No Content");
+
+ from("direct:bar")
+ .to("undertow:http://localhost:{{port}}/bar");
+
+
+ from("undertow:http://localhost:{{port}}/foobar")
+ .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200))
+ .setBody().constant("");
+
+ from("direct:foobar")
+ .to("undertow:http://localhost:{{port}}/foobar");
+
+ }
+ };
+ }
+}