You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Anton Koscejev (JIRA)" <ji...@apache.org> on 2015/10/29 09:59:27 UTC

[jira] [Comment Edited] (CAMEL-9270) rest-dsl - CORS support doesn't work with Restlet 2.3

    [ https://issues.apache.org/jira/browse/CAMEL-9270?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14980064#comment-14980064 ] 

Anton Koscejev edited comment on CAMEL-9270 at 10/29/15 8:58 AM:
-----------------------------------------------------------------

Warnings in log: 
{code}
2015-10-29 09:44:16,762 WARN [Restlet-1916677384] o.r.C.LogFilter [Slf4jLogger.java:283] Addition of the standard header "Access-Control-Allow-Headers" is not allowed. Please use the equivalent property in the Restlet API.
2015-10-29 09:44:16,762 WARN [Restlet-1916677384] o.r.C.LogFilter [Slf4jLogger.java:283] Addition of the standard header "Access-Control-Allow-Methods" is not allowed. Please use the equivalent property in the Restlet API.
2015-10-29 09:44:16,762 WARN [Restlet-1916677384] o.r.C.LogFilter [Slf4jLogger.java:283] Addition of the standard header "Access-Control-Allow-Origin" is not allowed. Please use the equivalent property in the Restlet API.
{code}

Workaround using custom RestletBinding:
{code}
import com.google.common.base.Splitter;
import org.restlet.data.Header;
import org.restlet.data.Method;
import org.restlet.util.Series;
import static com.google.common.collect.Sets.newHashSet;
import static org.restlet.engine.header.HeaderConstants.ATTRIBUTE_HEADERS;
...
public class CustomRestletBinding extends DefaultRestletBinding {
	private static final Splitter headerValueSplitter = Splitter.on(',').trimResults().omitEmptyStrings();

	@Override
	public void populateRestletResponseFromExchange(Exchange exchange, Response response) throws Exception {
		super.populateRestletResponseFromExchange(exchange, response);
		convertHeadersSupportedByRestletAPI(response);
	}

	/**
	 * Some headers are now supported by Restlet API and Restlet ignores them, if not set via API.
	 * This method sets them to Restlet Response via API and then removes these headers.
	 */
	private void convertHeadersSupportedByRestletAPI(Response response) {
		Iterator<Header> iterator = response.getHeaders().iterator();
		while (iterator.hasNext()) {
			Header header = iterator.next();
			if ("Access-Control-Allow-Origin".equals(header.getName())) {
				response.setAccessControlAllowOrigin(header.getValue());
			} else if ("Access-Control-Allow-Methods".equals(header.getName())) {
				response.setAccessControlAllowMethods(asMethods(header.getValue()));
			} else if ("Access-Control-Allow-Headers".equals(header.getName())) {
				response.setAccessControlAllowHeaders(asHeaders(header.getValue()));
			} else {
				continue; // do not remove all other headers
			}
			iterator.remove();
		}
	}

	@NotNull
	private Set<Method> asMethods(@NotNull String value) {
		return StreamSupport.stream(headerValueSplitter.split(value).spliterator(), false)
				.map(Method::valueOf)
				.collect(toSet());
	}

	@NotNull
	private HashSet<String> asHeaders(@NotNull String value) {
		return newHashSet(headerValueSplitter.split(value));
	}
}
{code}


was (Author: koscejev):
Warnings in log: 
{code}
2015-10-29 09:44:16,762 WARN [Restlet-1916677384] o.r.C.LogFilter [Slf4jLogger.java:283] Addition of the standard header "Access-Control-Allow-Headers" is not allowed. Please use the equivalent property in the Restlet API.
2015-10-29 09:44:16,762 WARN [Restlet-1916677384] o.r.C.LogFilter [Slf4jLogger.java:283] Addition of the standard header "Access-Control-Allow-Methods" is not allowed. Please use the equivalent property in the Restlet API.
2015-10-29 09:44:16,762 WARN [Restlet-1916677384] o.r.C.LogFilter [Slf4jLogger.java:283] Addition of the standard header "Access-Control-Allow-Origin" is not allowed. Please use the equivalent property in the Restlet API.
{code}

Workaround using custom RestletBinding:
{code}
import com.google.common.base.Splitter;
import org.restlet.data.Header;
import org.restlet.data.Method;
import org.restlet.util.Series;
import static com.google.common.collect.Sets.newHashSet;
import static org.restlet.engine.header.HeaderConstants.ATTRIBUTE_HEADERS;
...
public class CustomRestletBinding extends DefaultRestletBinding {
	private static final Splitter headerValueSplitter = Splitter.on(',').trimResults().omitEmptyStrings();

	@Override
	public void populateRestletResponseFromExchange(Exchange exchange, Response response) throws Exception {
		super.populateRestletResponseFromExchange(exchange, response);
		convertHeadersSupportedByRestletAPI(response);
	}

	/**
	 * Some headers are now supported by Restlet API and Restlet ignores them, if not set via API.
	 * This method sets them to Restlet Response via API and then removes these headers.
	 */
	private void convertHeadersSupportedByRestletAPI(Response response) {
		Series<Header> headers = getHeaders(response);
		Iterator<Header> iterator = headers.iterator();
		while (iterator.hasNext()) {
			Header header = iterator.next();
			if ("Access-Control-Allow-Origin".equals(header.getName())) {
				response.setAccessControlAllowOrigin(header.getValue());
			} else if ("Access-Control-Allow-Methods".equals(header.getName())) {
				response.setAccessControlAllowMethods(asMethods(header.getValue()));
			} else if ("Access-Control-Allow-Headers".equals(header.getName())) {
				response.setAccessControlAllowHeaders(asHeaders(header.getValue()));
			} else {
				continue; // do not remove all other headers
			}
			iterator.remove();
		}
	}

	@NotNull
	private Set<Method> asMethods(@NotNull String value) {
		return StreamSupport.stream(headerValueSplitter.split(value).spliterator(), false)
				.map(Method::valueOf)
				.collect(toSet());
	}

	@NotNull
	private HashSet<String> asHeaders(@NotNull String value) {
		return newHashSet(headerValueSplitter.split(value));
	}

	@SuppressWarnings("unchecked")
	protected Series<Header> getHeaders(org.restlet.Message restletMessage) {
		return (Series<Header>) restletMessage.getAttributes()
				.computeIfAbsent(ATTRIBUTE_HEADERS, k -> new Series<>(Header.class));
	}
}
{code}

> rest-dsl - CORS support doesn't work with Restlet 2.3
> -----------------------------------------------------
>
>                 Key: CAMEL-9270
>                 URL: https://issues.apache.org/jira/browse/CAMEL-9270
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core, camel-restlet
>    Affects Versions: 2.16.0
>            Reporter: Anton Koscejev
>
> camel-restlet has upgraded to Restlet 2.3 (nice!), but this broke rest-dsl CORS support, because Restlet 2.3 no longer supports setting CORS headers via attributes. There are now API methods for these headers and attributes are ignored with a warning.
> Example of the new API method:
> http://restlet.com/technical-resources/restlet-framework/javadocs/2.3/jse/api/org/restlet/Response.html#setAccessControlAllowOrigin%28java.lang.String%29



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)