Commit 8a2a608a by Spencer Gibb

Add zuul.removeSemicolonContent to enable matrix params.

fixes gh-542
parent 60f4a5bc
...@@ -87,7 +87,8 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { ...@@ -87,7 +87,8 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
@Bean @Bean
public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator) { public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator) {
return new PreDecorationFilter(routeLocator, return new PreDecorationFilter(routeLocator,
this.zuulProperties.isAddProxyHeaders()); this.zuulProperties.isAddProxyHeaders(),
this.zuulProperties.isRemoveSemicolonContent());
} }
// route filters // route filters
......
...@@ -74,6 +74,8 @@ public class ZuulProperties { ...@@ -74,6 +74,8 @@ public class ZuulProperties {
private boolean traceRequestBody = true; private boolean traceRequestBody = true;
private boolean removeSemicolonContent = true;
public Set<String> getIgnoredHeaders() { public Set<String> getIgnoredHeaders() {
Set<String> ignoredHeaders = new LinkedHashSet<>(this.ignoredHeaders); Set<String> ignoredHeaders = new LinkedHashSet<>(this.ignoredHeaders);
if (ClassUtils.isPresent( if (ClassUtils.isPresent(
......
...@@ -39,9 +39,10 @@ public class PreDecorationFilter extends ZuulFilter { ...@@ -39,9 +39,10 @@ public class PreDecorationFilter extends ZuulFilter {
private UrlPathHelper urlPathHelper = new UrlPathHelper(); private UrlPathHelper urlPathHelper = new UrlPathHelper();
public PreDecorationFilter(RouteLocator routeLocator, boolean addProxyHeaders) { public PreDecorationFilter(RouteLocator routeLocator, boolean addProxyHeaders, boolean removeSemicolonContent) {
this.routeLocator = routeLocator; this.routeLocator = routeLocator;
this.addProxyHeaders = addProxyHeaders; this.addProxyHeaders = addProxyHeaders;
this.urlPathHelper.setRemoveSemicolonContent(removeSemicolonContent);
} }
@Override @Override
......
...@@ -50,6 +50,8 @@ import org.springframework.test.annotation.DirtiesContext; ...@@ -50,6 +50,8 @@ import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.MatrixVariable;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
...@@ -60,19 +62,20 @@ import com.netflix.loadbalancer.Server; ...@@ -60,19 +62,20 @@ import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList; import com.netflix.loadbalancer.ServerList;
import com.netflix.niws.client.http.RestClient; import com.netflix.niws.client.http.RestClient;
import lombok.SneakyThrows;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import lombok.SneakyThrows;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleZuulProxyApplication.class) @SpringApplicationConfiguration(classes = SampleZuulProxyApplication.class)
@WebAppConfiguration @WebAppConfiguration
@IntegrationTest({ "server.port: 0", @IntegrationTest({"server.port: 0",
"zuul.routes.other: /test/**=http://localhost:7777/local", "zuul.routes.other: /test/**=http://localhost:7777/local",
"zuul.routes.another: /another/twolevel/**", "zuul.routes.simple: /simple/**", "zuul.routes.another: /another/twolevel/**", "zuul.routes.simple: /simple/**",
"zuul.routes.badhost: /badhost/**", "zuul.ignoredHeaders: X-Header" }) "zuul.routes.badhost: /badhost/**", "zuul.ignoredHeaders: X-Header",
"zuul.removeSemicolonContent: false"})
@DirtiesContext @DirtiesContext
public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase { public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase {
...@@ -122,12 +125,24 @@ public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase { ...@@ -122,12 +125,24 @@ public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase {
} }
@Test @Test
public void simpleHostRouteWithMatrix() {
this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/");
this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/self/matrix/my;q=2;p=1/more;x=2",
HttpMethod.GET, new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("my=1-2;more=2", result.getBody());
}
@Test
public void simpleHostRouteWithEncodedQuery() { public void simpleHostRouteWithEncodedQuery() {
this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/"); this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/");
this.endpoint.reset(); this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange( ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/self/query?foo={foo}", HttpMethod.GET, "http://localhost:" + this.port + "/self/query?foo={foo}",
new HttpEntity<>((Void) null), String.class, "weird#chars"); HttpMethod.GET, new HttpEntity<>((Void) null), String.class,
"weird#chars");
assertEquals(HttpStatus.OK, result.getStatusCode()); assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("/query?foo=weird#chars", result.getBody()); assertEquals("/query?foo=weird#chars", result.getBody());
} }
...@@ -175,12 +190,12 @@ public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase { ...@@ -175,12 +190,12 @@ public class SampleZuulProxyApplicationTests extends ZuulProxyTestBase {
@RibbonClient(name = "another", configuration = AnotherRibbonClientConfiguration.class) }) @RibbonClient(name = "another", configuration = AnotherRibbonClientConfiguration.class) })
class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyApplication { class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyApplication {
@RequestMapping(value = "/trailing-slash") @RequestMapping("/trailing-slash")
public String trailingSlash(HttpServletRequest request) { public String trailingSlash(HttpServletRequest request) {
return request.getRequestURI(); return request.getRequestURI();
} }
@RequestMapping(value = "/add-header") @RequestMapping("/add-header")
public ResponseEntity<String> addHeader(HttpServletRequest request) { public ResponseEntity<String> addHeader(HttpServletRequest request) {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.set("X-Header", "FOO"); headers.set("X-Header", "FOO");
...@@ -189,11 +204,19 @@ class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyAppl ...@@ -189,11 +204,19 @@ class SampleZuulProxyApplication extends ZuulProxyTestBase.AbstractZuulProxyAppl
return result; return result;
} }
@RequestMapping(value = "/query") @RequestMapping("/query")
public String addQuery(HttpServletRequest request, @RequestParam String foo) { public String addQuery(HttpServletRequest request, @RequestParam String foo) {
return request.getRequestURI() + "?foo=" + foo; return request.getRequestURI() + "?foo=" + foo;
} }
@RequestMapping("/matrix/{name}/{another}")
public String matrix(@PathVariable("name") String name,
@MatrixVariable(value = "p", pathVar = "name") int p,
@MatrixVariable(value = "q", pathVar = "name") int q,
@PathVariable("another") String another, @MatrixVariable(value = "x", pathVar = "another") int x) {
return name + "=" + p + "-" + q + ";" + another + "=" + x;
}
@Bean @Bean
public RibbonCommandFactory<?> ribbonCommandFactory( public RibbonCommandFactory<?> ribbonCommandFactory(
SpringClientFactory clientFactory) { SpringClientFactory clientFactory) {
......
...@@ -27,6 +27,8 @@ import org.springframework.web.bind.annotation.RequestBody; ...@@ -27,6 +27,8 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList; import com.netflix.loadbalancer.ServerList;
...@@ -182,7 +184,7 @@ public abstract class ZuulProxyTestBase { ...@@ -182,7 +184,7 @@ public abstract class ZuulProxyTestBase {
assertEquals("Received {key=[overridden]}", result.getBody()); assertEquals("Received {key=[overridden]}", result.getBody());
} }
protected static abstract class AbstractZuulProxyApplication { protected static abstract class AbstractZuulProxyApplication extends DelegatingWebMvcConfiguration {
@RequestMapping("/testing123") @RequestMapping("/testing123")
public String testing123() { public String testing123() {
...@@ -258,6 +260,13 @@ public abstract class ZuulProxyTestBase { ...@@ -258,6 +260,13 @@ public abstract class ZuulProxyTestBase {
} }
}; };
} }
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping mapping = super.requestMappingHandlerMapping();
mapping.setRemoveSemicolonContent(false);
return mapping;
}
} }
} }
......
...@@ -54,7 +54,8 @@ public class PreDecorationFilterTests { ...@@ -54,7 +54,8 @@ public class PreDecorationFilterTests {
initMocks(this); initMocks(this);
this.routeLocator = new DiscoveryClientRouteLocator("/", this.discovery, this.routeLocator = new DiscoveryClientRouteLocator("/", this.discovery,
this.properties); this.properties);
this.filter = new PreDecorationFilter(this.routeLocator, true); this.filter = new PreDecorationFilter(this.routeLocator, true,
this.properties.isRemoveSemicolonContent());
RequestContext ctx = RequestContext.getCurrentContext(); RequestContext ctx = RequestContext.getCurrentContext();
ctx.clear(); ctx.clear();
ctx.setRequest(this.request); ctx.setRequest(this.request);
......
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