CAMEL-6879: camel-restlet consumer should send back HTTP headers, such as Location etc.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/66648ee0 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/66648ee0 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/66648ee0 Branch: refs/heads/camel-2.12.x Commit: 66648ee0478a6834d9191b38caa0c290ab253f12 Parents: 204d6ef Author: Claus Ibsen <davscl...@apache.org> Authored: Mon Oct 21 10:00:30 2013 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Mon Oct 21 10:09:49 2013 +0200 ---------------------------------------------------------------------- .../restlet/DefaultRestletBinding.java | 45 ++++++++++--- .../restlet/RestletHeaderFilterStrategy.java | 7 +- .../component/restlet/RestletRedirectTest.java | 68 ++++++++++++++++++++ 3 files changed, 108 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/66648ee0/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/DefaultRestletBinding.java ---------------------------------------------------------------------- diff --git a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/DefaultRestletBinding.java b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/DefaultRestletBinding.java index f84511e..055d251 100644 --- a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/DefaultRestletBinding.java +++ b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/DefaultRestletBinding.java @@ -49,10 +49,14 @@ import org.restlet.data.MediaType; import org.restlet.data.Method; import org.restlet.data.Preference; import org.restlet.data.Status; +import org.restlet.engine.adapter.HttpResponse; +import org.restlet.engine.header.Header; import org.restlet.engine.header.HeaderConstants; +import org.restlet.engine.header.HeaderUtils; import org.restlet.representation.FileRepresentation; import org.restlet.representation.InputRepresentation; import org.restlet.representation.Representation; +import org.restlet.util.Series; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -250,14 +254,31 @@ public class DefaultRestletBinding implements RestletBinding, HeaderFilterStrate } // set headers at the end, as the entity must be set first + // NOTE: setting HTTP headers on restlet is cumbersome and its API is "weird" and has some flaws + // so we need to headers two times, and the 2nd time we add the non-internal headers once more + Series<Header> series = new Series<Header>(Header.class); for (Map.Entry<String, Object> entry : out.getHeaders().entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); if (!headerFilterStrategy.applyFilterToCamelHeaders(key, value, exchange)) { - setResponseHeader(exchange, response, key, value); - LOG.debug("Populate Restlet HTTP header in response from exchange header: {} value: {}", key, value); + boolean added = setResponseHeader(exchange, response, key, value); + if (!added) { + // we only want non internal headers + if (!key.startsWith("Camel") && !key.startsWith("org.restlet")) { + String text = exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange, value); + if (text != null) { + series.add(key, text); + } + } + } } } + + // set HTTP headers so we return these in the response + if (!series.isEmpty()) { + Series<Header> httpHeaders = (Series<Header>) response.getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS); + httpHeaders.addAll(series); + } } public void populateExchangeFromRestletResponse(Exchange exchange, Response response) throws Exception { @@ -295,17 +316,16 @@ public class DefaultRestletBinding implements RestletBinding, HeaderFilterStrate MessageHelper.copyHeaders(exchange.getIn(), exchange.getOut(), false); } - @SuppressWarnings("unchecked") - protected void setResponseHeader(Exchange exchange, org.restlet.Message message, String header, Object value) { - // put the header first - message.getAttributes().put(header, value); - + protected boolean setResponseHeader(Exchange exchange, org.restlet.Message message, String header, Object value) { // there must be a value going forward if (value == null) { - return; + return true; } - + + // must put to attributes + message.getAttributes().put(header, value); + // special for certain headers if (message.getEntity() != null) { if (header.equalsIgnoreCase(HeaderConstants.HEADER_CACHE_CONTROL)) { @@ -318,6 +338,7 @@ public class DefaultRestletBinding implements RestletBinding, HeaderFilterStrate list.add(new CacheDirective((String) value)); message.setCacheDirectives(list); } + return true; } if (header.equalsIgnoreCase(HeaderConstants.HEADER_EXPIRES)) { if (value instanceof Calendar) { @@ -333,6 +354,7 @@ public class DefaultRestletBinding implements RestletBinding, HeaderFilterStrate LOG.debug("Header {} with value {} cannot be converted as a Date. The value will be ignored.", HeaderConstants.HEADER_EXPIRES, value); } } + return true; } if (header.equalsIgnoreCase(HeaderConstants.HEADER_LAST_MODIFIED)) { @@ -349,6 +371,7 @@ public class DefaultRestletBinding implements RestletBinding, HeaderFilterStrate LOG.debug("Header {} with value {} cannot be converted as a Date. The value will be ignored.", HeaderConstants.HEADER_LAST_MODIFIED, value); } } + return true; } if (header.equalsIgnoreCase(HeaderConstants.HEADER_CONTENT_LENGTH)) { @@ -364,6 +387,7 @@ public class DefaultRestletBinding implements RestletBinding, HeaderFilterStrate LOG.debug("Header {} with value {} cannot be converted as a Long. The value will be ignored.", HeaderConstants.HEADER_CONTENT_LENGTH, value); } } + return true; } if (header.equalsIgnoreCase(HeaderConstants.HEADER_CONTENT_TYPE)) { @@ -378,8 +402,11 @@ public class DefaultRestletBinding implements RestletBinding, HeaderFilterStrate LOG.debug("Header {} with value {} cannot be converted as a MediaType. The value will be ignored.", HeaderConstants.HEADER_CONTENT_TYPE, value); } } + return true; } } + + return false; } public HeaderFilterStrategy getHeaderFilterStrategy() { http://git-wip-us.apache.org/repos/asf/camel/blob/66648ee0/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletHeaderFilterStrategy.java ---------------------------------------------------------------------- diff --git a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletHeaderFilterStrategy.java b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletHeaderFilterStrategy.java index b873230..4ef196b 100644 --- a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletHeaderFilterStrategy.java +++ b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletHeaderFilterStrategy.java @@ -38,8 +38,9 @@ public class RestletHeaderFilterStrategy extends DefaultHeaderFilterStrategy { // The "CamelAcceptContentType" header is not added to the outgoing HTTP // headers but it will be going out as "Accept. getOutFilter().add(Exchange.ACCEPT_CONTENT_TYPE); - - // Remove the restlet headers from the out message. - getOutFilter().add(HeaderConstants.ATTRIBUTE_HEADERS); + + // Remove Camel and org.restlet internal headers +// setOutFilterPattern("(Camel.*)|(org\\.restlet\\..*)"); +// setOutFilterPattern("org\\.restlet\\..*"); } } http://git-wip-us.apache.org/repos/asf/camel/blob/66648ee0/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestletRedirectTest.java ---------------------------------------------------------------------- diff --git a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestletRedirectTest.java b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestletRedirectTest.java new file mode 100644 index 0000000..a54c5c1 --- /dev/null +++ b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestletRedirectTest.java @@ -0,0 +1,68 @@ +/** + * 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.restlet; + +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.params.ClientPNames; +import org.apache.http.impl.client.DefaultHttpClient; +import org.junit.Test; + +/** + * + * @version + */ +public class RestletRedirectTest extends RestletTestSupport { + + @Test + public void testRedirect() throws Exception { + HttpGet get = new HttpGet("http://localhost:" + portNum + "/users/homer"); + + // do not follow redirects + HttpClient client = new DefaultHttpClient(); + client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); + + HttpResponse response = client.execute(get); + + for (Header header : response.getAllHeaders()) { + log.info("Header {}", header); + } + + assertEquals(302, response.getStatusLine().getStatusCode()); + assertTrue("Should have location header", response.containsHeader("Location")); + assertEquals("http://somewhere.com", response.getFirstHeader("Location").getValue()); + assertEquals("bar", response.getFirstHeader("Foo").getValue()); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("restlet:http://localhost:" + portNum + "/users/{username}") + .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(302)) + .setHeader("Location", constant("http://somewhere.com")) + .setHeader("Foo", constant("bar")); + } + }; + } + +} \ No newline at end of file