Commit 7f075d11 by Dave Syer

Allow Cors requests through to backend by default

Instead of blocking them (which is the default behaviour of a Spring MVC controller) Cors requests will flow through the Zuul filters by default. Users can control it by grabbing the ZuulHandlerMapping in a @PostConstruct and injecting some CorsConfiguration via its setCorsConfigurations() method.
parent a38b7b71
......@@ -37,9 +37,10 @@ public class ZuulController extends ServletWrappingController {
}
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
// We don't care about the other features of the base class, just want to
// handle the request
return super.handleRequestInternal(request, response);
}
finally {
......
......@@ -25,6 +25,8 @@ import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
import com.netflix.zuul.context.RequestContext;
......@@ -51,6 +53,16 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {
setOrder(-200);
}
@Override
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
HandlerExecutionChain chain, CorsConfiguration config) {
if (config == null) {
// Allow CORS requests to go to the backend
return chain;
}
return super.getCorsHandlerExecutionChain(request, chain, config);
}
public void setErrorController(ErrorController errorController) {
this.errorController = errorController;
}
......@@ -63,10 +75,8 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {
}
@Override
protected Object lookupHandler(String urlPath, HttpServletRequest request)
throws Exception {
if (this.errorController != null
&& urlPath.equals(this.errorController.getErrorPath())) {
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
if (this.errorController != null && urlPath.equals(this.errorController.getErrorPath())) {
return null;
}
String[] ignored = this.routeLocator.getIgnoredPaths().toArray(new String[0]);
......
......@@ -18,6 +18,9 @@ package org.springframework.cloud.netflix.zuul;
import static org.junit.Assert.assertEquals;
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -33,13 +36,16 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClientException;
import com.netflix.zuul.context.RequestContext;
......@@ -68,9 +74,38 @@ public class ServletPathZuulProxyApplicationTests {
public void getOnSelfViaSimpleHostRoutingFilter() {
this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/app/local");
this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange("http://localhost:" + this.port + "/app/self/1",
HttpMethod.GET, new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Gotten 1!", result.getBody());
}
@Test
public void optionsOnRawEndpoint() throws Exception {
ResponseEntity<String> result = new TestRestTemplate().exchange(RequestEntity
.options(new URI("http://localhost:" + this.port + "/app/local/1"))
.header("Origin", "http://localhost:9000").header("Access-Control-Request-Method", "GET").build(),
String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("http://localhost:9000", result.getHeaders().getFirst("Access-Control-Allow-Origin"));
}
@Test
public void optionsOnSelf() throws Exception {
this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/app/local");
this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange(RequestEntity
.options(new URI("http://localhost:" + this.port + "/app/self/1"))
.header("Origin", "http://localhost:9000").header("Access-Control-Request-Method", "GET").build(),
String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("http://localhost:9000", result.getHeaders().getFirst("Access-Control-Allow-Origin"));
}
@Test
public void contentOnRawEndpoint() throws Exception {
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/app/self/1", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
RequestEntity.get(new URI("http://localhost:" + this.port + "/app/local/1")).build(), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Gotten 1!", result.getBody());
}
......@@ -80,9 +115,8 @@ public class ServletPathZuulProxyApplicationTests {
this.routes.addRoute(new ZuulRoute("strip", "/strip/**", "strip",
"http://localhost:" + this.port + "/app/local", false, false, null));
this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/app/strip", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
ResponseEntity<String> result = new TestRestTemplate().exchange("http://localhost:" + this.port + "/app/strip",
HttpMethod.GET, new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
// Prefix not stripped to it goes to /local/strip
assertEquals("Gotten strip!", result.getBody());
......@@ -96,6 +130,7 @@ public class ServletPathZuulProxyApplicationTests {
static class ServletPathZuulProxyApplication {
@RequestMapping(value = "/local/{id}", method = RequestMethod.GET)
@CrossOrigin(origins = "*")
public String get(@PathVariable String id) {
return "Gotten " + id + "!";
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment