Add CORS interceptor for Cloud Foundry actuators
This interceptor processes the response with CORS headers and apepars before the Cloud Foundry security interceptor. See gh-7108
This commit is contained in:
parent
f35fa87366
commit
3a3228fc70
|
|
@ -23,6 +23,7 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.AbstractEndpointHandlerMapping;
|
||||
|
|
@ -34,6 +35,7 @@ import org.springframework.web.cors.CorsConfiguration;
|
|||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
/**
|
||||
* {@link HandlerMapping} to map {@link Endpoint}s to Cloud Foundry specific URLs.
|
||||
|
|
@ -45,10 +47,13 @@ class CloudFoundryEndpointHandlerMapping
|
|||
|
||||
private final HandlerInterceptor securityInterceptor;
|
||||
|
||||
private final CorsConfiguration corsConfiguration;
|
||||
|
||||
CloudFoundryEndpointHandlerMapping(Set<? extends NamedMvcEndpoint> endpoints,
|
||||
CorsConfiguration corsConfiguration, HandlerInterceptor securityInterceptor) {
|
||||
super(endpoints, corsConfiguration);
|
||||
this.securityInterceptor = securityInterceptor;
|
||||
this.corsConfiguration = corsConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -97,6 +102,7 @@ class CloudFoundryEndpointHandlerMapping
|
|||
|
||||
private HandlerInterceptor[] addSecurityInterceptor(HandlerInterceptor[] existing) {
|
||||
List<HandlerInterceptor> interceptors = new ArrayList<HandlerInterceptor>();
|
||||
interceptors.add(new CorsInterceptor(this.corsConfiguration));
|
||||
interceptors.add(this.securityInterceptor);
|
||||
if (existing != null) {
|
||||
interceptors.addAll(Arrays.asList(existing));
|
||||
|
|
@ -104,4 +110,23 @@ class CloudFoundryEndpointHandlerMapping
|
|||
return interceptors.toArray(new HandlerInterceptor[interceptors.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link HandlerInterceptor} that processes the response for CORS.
|
||||
*
|
||||
*/
|
||||
class CorsInterceptor extends HandlerInterceptorAdapter {
|
||||
private final CorsConfiguration config;
|
||||
|
||||
CorsInterceptor(CorsConfiguration config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
return getCorsProcessor().processRequest(this.config, request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ import org.springframework.boot.actuate.health.HealthIndicator;
|
|||
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsProcessor;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
|
@ -47,6 +50,25 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
public class CloudFoundryEndpointHandlerMappingTests
|
||||
extends AbstractEndpointHandlerMappingTests {
|
||||
|
||||
@Test
|
||||
public void corsInterceptorShouldBeFirstAndCallCorsProcessor() throws Exception {
|
||||
TestMvcEndpoint endpoint = new TestMvcEndpoint(new TestEndpoint("a"));
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
CloudFoundryEndpointHandlerMapping handlerMapping = new CloudFoundryEndpointHandlerMapping(
|
||||
Collections.singleton(endpoint), corsConfiguration, null);
|
||||
CorsProcessor corsProcessor = Mockito.mock(CorsProcessor.class);
|
||||
handlerMapping.setCorsProcessor(corsProcessor);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
HandlerExecutionChain handlerExecutionChain = handlerMapping
|
||||
.getHandlerExecutionChain(endpoint, request);
|
||||
HandlerInterceptor[] interceptors = handlerExecutionChain.getInterceptors();
|
||||
CloudFoundryEndpointHandlerMapping.CorsInterceptor corsInterceptor = (CloudFoundryEndpointHandlerMapping.CorsInterceptor) interceptors[0];
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
corsInterceptor.preHandle(request, response, new Object());
|
||||
Mockito.verify(corsProcessor).processRequest(corsConfiguration, request,
|
||||
response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerExecutionChainShouldHaveSecurityInterceptor() throws Exception {
|
||||
CloudFoundrySecurityInterceptor securityInterceptor = Mockito
|
||||
|
|
@ -57,7 +79,7 @@ public class CloudFoundryEndpointHandlerMappingTests
|
|||
HandlerExecutionChain handlerExecutionChain = handlerMapping
|
||||
.getHandlerExecutionChain(endpoint, new MockHttpServletRequest());
|
||||
HandlerInterceptor[] interceptors = handlerExecutionChain.getInterceptors();
|
||||
assertThat(interceptors).contains(securityInterceptor);
|
||||
assertThat(interceptors[1]).isEqualTo(securityInterceptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue