Skip to content

Commit

Permalink
Replace CORS serlvet filter with a @Provider ContainerResponseFilter …
Browse files Browse the repository at this point in the history
…impl.
  • Loading branch information
jsyrjala committed Sep 29, 2014
1 parent 99085f3 commit 2db3f1c
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 86 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import javax.servlet.DispatcherType;

import org.apache.cxf.transport.servlet.CXFServlet;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.NCSARequestLog;
Expand Down Expand Up @@ -110,7 +107,6 @@ protected void setupSpring(final ServletContextHandler context, ConfigurableEnvi
}

protected void setupCxf(final ServletContextHandler context) {
context.addFilter(CorsHeaderFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
ServletHolder servlet = context.addServlet(CXFServlet.class, "/*");
servlet.setDisplayName("cxf-services");
servlet.setInitOrder(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.Arrays;

import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
Expand All @@ -25,6 +26,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.nitorcreations.nflow.jetty.validation.CustomValidationExceptionMapper;
import com.nitorcreations.nflow.rest.config.CorsHeaderContainerResponseFilter;
import com.nitorcreations.nflow.rest.config.RestConfiguration;
import com.nitorcreations.nflow.rest.v1.WorkflowDefinitionResource;
import com.nitorcreations.nflow.rest.v1.WorkflowInstanceResource;
Expand All @@ -39,6 +41,9 @@
@Import(value = { RestConfiguration.class, JmxConfiguration.class})
public class NflowJettyConfiguration {

@Inject
private Environment env;

@Bean
public Server jaxRsServer(WorkflowInstanceResource workflowInstanceResource, WorkflowDefinitionResource workflowDefinitionResource, @Named("nflowRestObjectMapper") ObjectMapper mapper) {
JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint(jaxRsApiApplication(), JAXRSServerFactoryBean.class);
Expand All @@ -47,18 +52,24 @@ public Server jaxRsServer(WorkflowInstanceResource workflowInstanceResource, Wor
workflowDefinitionResource,
apiListingResourceJson()));
factory.setAddress('/' + factory.getAddress());
factory.setProviders( Arrays.< Object >asList(
factory.setProviders( Arrays.asList(
jsonProvider(mapper),
validationExceptionMapper(),
resourceListingProvider(),
apiDeclarationProvider()) );
apiDeclarationProvider(),
corsHeadersProvider()
));
factory.setFeatures(Arrays.asList(new LoggingFeature()));
factory.setBus(cxf());
factory.setInInterceptors(Arrays.< Interceptor< ? extends Message > >asList(new JAXRSBeanValidationInInterceptor()));
factory.setOutInterceptors(Arrays.< Interceptor< ? extends Message > >asList(new JAXRSBeanValidationOutInterceptor()));
return factory.create();
}

private CorsHeaderContainerResponseFilter corsHeadersProvider() {
return new CorsHeaderContainerResponseFilter(env);
}

@Bean
public JacksonJsonProvider jsonProvider(@Named("nflowRestObjectMapper") ObjectMapper mapper) {
return new JacksonJsonProvider(mapper);
Expand Down
3 changes: 2 additions & 1 deletion nflow-jetty/src/main/resources/nflow-jetty.properties
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
jetty.host=0.0.0.0
jetty.host=0.0.0.0
nflow.rest.allow.origin=*

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.nitorcreations.nflow.rest.config;

import javax.inject.Inject;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;

import org.springframework.core.env.Environment;

/**
* Filter to add headers to allow Cross-Origin Resource Sharing.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
*/
@Provider
public class CorsHeaderContainerResponseFilter implements ContainerResponseFilter {

private final Environment env;

@Inject
public CorsHeaderContainerResponseFilter(final Environment env) {
this.env = env;
}

@Override
public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) {
String origin = env.getProperty("nflow.rest.allow.origin", "*");
responseContext.getHeaders().add("Access-Control-Allow-Origin", origin);
responseContext.getHeaders().add("Access-Control-Allow-Headers",
"X-Requested-With, Content-Type, Origin, Referer, User-Agent, Accept");
responseContext.getHeaders().add("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, DELETE");
// for cookies?
responseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.nitorcreations.nflow.rest.config;

import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.env.Environment;

@RunWith(MockitoJUnitRunner.class)
public class CorsHeaderContainerResponseFilterTest {

@Mock
ContainerRequestContext requestContext;
@Mock
ContainerResponseContext responseContext;
@Mock
Environment env;
CorsHeaderContainerResponseFilter filter;
MultivaluedMap<String, Object> headerMap = new MultivaluedHashMap<>();

@Before
public void setup() {
filter = new CorsHeaderContainerResponseFilter(env);
when(responseContext.getHeaders()).thenReturn(headerMap);
}

@Test
public void addsHeaders() {
String host="example.com";
when(env.getProperty("nflow.rest.allow.origin", "*")).thenReturn(host);

filter.filter(requestContext, responseContext);

assertEquals(asList(host), headerMap.get("Access-Control-Allow-Origin"));
assertEquals(asList("X-Requested-With, Content-Type, Origin, Referer, User-Agent, Accept"),
headerMap.get("Access-Control-Allow-Headers"));
assertEquals(asList("OPTIONS, GET, POST, PUT, DELETE"), headerMap.get("Access-Control-Allow-Methods"));
assertEquals(asList("true"), headerMap.get("Access-Control-Allow-Credentials"));
}

}

0 comments on commit 2db3f1c

Please sign in to comment.