Use UrlPathHelper to determine the current url path in Zuul
If the app has a context path then the route locator does not match the whole requestURI (as provided by the raw servlet API), but Spring has a utility for stripping it off, so we can just use that. Fixes gh-270
This commit is contained in:
@@ -26,6 +26,7 @@ import lombok.extern.apachecommons.CommonsLog;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ProxyRouteLocator;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ProxyRouteLocator.ProxyRouteSpec;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
@@ -37,6 +38,8 @@ public class PreDecorationFilter extends ZuulFilter {
|
||||
|
||||
private boolean addProxyHeaders;
|
||||
|
||||
private UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
|
||||
public PreDecorationFilter(ProxyRouteLocator routeLocator, boolean addProxyHeaders) {
|
||||
this.routeLocator = routeLocator;
|
||||
this.addProxyHeaders = addProxyHeaders;
|
||||
@@ -60,18 +63,19 @@ public class PreDecorationFilter extends ZuulFilter {
|
||||
@Override
|
||||
public Object run() {
|
||||
RequestContext ctx = RequestContext.getCurrentContext();
|
||||
final String requestURI = ctx.getRequest().getRequestURI();
|
||||
final String requestURI = this.urlPathHelper.getPathWithinApplication(ctx
|
||||
.getRequest());
|
||||
ProxyRouteSpec route = this.routeLocator.getMatchingRoute(requestURI);
|
||||
if (route != null) {
|
||||
String location = route.getLocation();
|
||||
if (location != null) {
|
||||
ctx.put("requestURI", route.getPath());
|
||||
ctx.put("proxy", route.getId());
|
||||
|
||||
|
||||
if (route.getRetryable() != null) {
|
||||
ctx.put("retryable", route.getRetryable());
|
||||
}
|
||||
|
||||
|
||||
if (location.startsWith("http:") || location.startsWith("https:")) {
|
||||
ctx.setRouteHost(getUrl(location));
|
||||
ctx.addOriginResponseHeader("X-Zuul-Service", location);
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.zuul;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.boot.test.TestRestTemplate;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ProxyRouteLocator;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
|
||||
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.ResponseEntity;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
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 static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = ContextPathZuulProxyApplication.class)
|
||||
@WebAppConfiguration
|
||||
@IntegrationTest({ "server.port: 0", "server.contextPath: /app" })
|
||||
@DirtiesContext
|
||||
public class ContextPathZuulProxyApplicationTests {
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private int port;
|
||||
|
||||
@Autowired
|
||||
private ProxyRouteLocator routes;
|
||||
|
||||
@Autowired
|
||||
private RoutesEndpoint endpoint;
|
||||
|
||||
@Test
|
||||
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 stripPrefixFalseAppendsPath() {
|
||||
this.routes.addRoute(new ZuulRoute("strip", "/strip/**", "strip",
|
||||
"http://localhost:" + this.port + "/app/local", false, false));
|
||||
this.endpoint.reset();
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Don't use @SpringBootApplication because we don't want to component scan
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
@EnableZuulProxy
|
||||
class ContextPathZuulProxyApplication {
|
||||
|
||||
@RequestMapping(value = "/local/{id}", method = RequestMethod.GET)
|
||||
public String get(@PathVariable String id) {
|
||||
return "Gotten " + id + "!";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SampleZuulProxyApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user