Strip prefixes from zuul routes by default
The default behaviour is now to strip the prefixes (global and
route-specific) by default. E.g.
zuul:
prefix: /api
routes:
customers: /customers/**
Will forward /api/customers/101 to /101 on the customers service
See gh-43
This commit is contained in:
@@ -500,10 +500,26 @@ Zuul's rule engine allows rules and filters to be written in essentially any JVM
|
||||
[[netflix-zuul-reverse-proxy]]
|
||||
=== Embedded Zuul Reverse Proxy
|
||||
|
||||
Spring Cloud has created an embedded Zuul proxy to ease the development of a very common use case where a UI application wants to proxy calls to one or more back end services. To enable it, annotate a Spring Boot main class with `@EnableZuulProxy`, and this forwards local calls to the appropriate service. By convention, a service with the Eureka ID "users", will receive requests from the proxy located at `/users`. The proxy uses Ribbon to locate an instance to forward to via Eureka. To skip having a service automatically added from eureka, set `zuul.ignored-services = service1`.
|
||||
Spring Cloud has created an embedded Zuul proxy to ease the
|
||||
development of a very common use case where a UI application wants to
|
||||
proxy calls to one or more back end services. This feature is useful
|
||||
for a user interface to proxy to the backend services it requires,
|
||||
avoiding the need to manage CORS and authentication concerns
|
||||
independently for all the backends.
|
||||
|
||||
To augment or change the proxy routes, you can add external
|
||||
configuration like the following:
|
||||
To enable it, annotate a Spring Boot main class with
|
||||
`@EnableZuulProxy`, and this forwards local calls to the appropriate
|
||||
service. By convention, a service with the Eureka ID "users", will
|
||||
receive requests from the proxy located at `/users` (with the prefix
|
||||
stripped). The proxy uses Ribbon to locate an instance to forward to
|
||||
via Eureka, and all requests are executed in a hystrix command, so
|
||||
failures will show up in Hystrix metrics, and once the circuit is open
|
||||
the proxy will not try to contact the service.
|
||||
|
||||
To skip having a service automatically added, set
|
||||
`zuul.ignored-services` to a list of service ids. To augment or change
|
||||
the proxy routes, you can add external configuration like the
|
||||
following:
|
||||
|
||||
.application.yml
|
||||
[source,yaml]
|
||||
@@ -514,9 +530,7 @@ configuration like the following:
|
||||
----
|
||||
|
||||
This means that http calls to "/myusers" get forwarded to the "users"
|
||||
service. This configuration is useful for a user interface to proxy to
|
||||
the backend services it requires (avoiding the need to manage CORS and
|
||||
authentication concerns independently for all the backends).
|
||||
service (for example "/myusers/101" is forwarded to "/101").
|
||||
|
||||
To get more fine-grained control over a route you can specify the path
|
||||
and the serviceId independently:
|
||||
@@ -549,9 +563,11 @@ The location of the backend can be specified as either a "serviceId"
|
||||
url: http://example.com/users_service
|
||||
----
|
||||
|
||||
Forwarding to the service is protected by a Hystrix circuit breaker so if a service is down the client will see an error, but once the circuit is open the proxy will not try to contact the service.
|
||||
|
||||
To add a prefix to all mappings, set `zuul.prefix` to a value, such as `/api`. To strip the proxy prefix from the request before the request is forwarded set `zuul.stripPrefix = true`. You can also strip the non-wildcard prefix from individual routes, e.g.
|
||||
To add a prefix to all mappings, set `zuul.prefix` to a value, such as
|
||||
`/api`. The proxy prefix is stripped from the request before the
|
||||
request is forwarded by default (switch this behaviour off with
|
||||
`zuul.stripPrefix=false`). You can also switch off the stripping of
|
||||
the service-specific prefix from individual routes, e.g.
|
||||
|
||||
.application.yml
|
||||
[source,yaml]
|
||||
@@ -560,12 +576,18 @@ To add a prefix to all mappings, set `zuul.prefix` to a value, such as `/api`.
|
||||
routes:
|
||||
users:
|
||||
path: /myusers/**
|
||||
stripPrefix: true
|
||||
stripPrefix: false
|
||||
----
|
||||
|
||||
In this example requests to "/myusers/101" will be forwarded to "/101" on the "users" service (the path is stripped up to the first wildcard character).
|
||||
In this example requests to "/myusers/101" will be forwarded to "/myusers/101" on the "users" service.
|
||||
|
||||
The `X-Forwarded-Host` header added to the forwarded requests by default. To turn it off set `zuul.addProxyHeaders = false`.
|
||||
The `X-Forwarded-Host` header added to the forwarded requests by
|
||||
default. To turn it off set `zuul.addProxyHeaders = false`. The
|
||||
prefix path is stripped by default, and the request to the backend
|
||||
picks up a header "X-Forwarded-Prefix" ("/myusers" in the examples
|
||||
above).
|
||||
|
||||
An application with the `@EnableZuulProxy` could act as a standalone server if you set a default route ("/"), for example `zuul.route.home: /` would route all traffic (i.e. "/**") to the "home" service.
|
||||
An application with the `@EnableZuulProxy` could act as a standalone
|
||||
server if you set a default route ("/"), for example `zuul.route.home:
|
||||
/` would route all traffic (i.e. "/**") to the "home" service.
|
||||
|
||||
|
||||
@@ -85,9 +85,9 @@ public class ProxyRouteLocator {
|
||||
if (route.isStripPrefix()) {
|
||||
int index = route.getPath().indexOf("*") - 1;
|
||||
if (index > 0) {
|
||||
targetPath = path.substring(prefix.length() + index);
|
||||
prefix = prefix
|
||||
+ path.substring(prefix.length(), prefix.length() + index);
|
||||
String routePrefix = route.getPath().substring(0, index);
|
||||
targetPath = targetPath.replaceFirst(routePrefix, "");
|
||||
prefix = prefix + routePrefix;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.springframework.util.StringUtils;
|
||||
@ConfigurationProperties("zuul")
|
||||
public class ZuulProperties {
|
||||
private String prefix = "";
|
||||
private boolean stripPrefix = false;
|
||||
private boolean stripPrefix = true;
|
||||
private Map<String, ZuulRoute> routes = new LinkedHashMap<String, ZuulRoute>();
|
||||
private boolean addProxyHeaders = true;
|
||||
private List<String> ignoredServices = new ArrayList<String>();
|
||||
@@ -43,7 +43,7 @@ public class ZuulProperties {
|
||||
private String path;
|
||||
private String serviceId;
|
||||
private String url;
|
||||
private boolean stripPrefix = false;
|
||||
private boolean stripPrefix = true;
|
||||
|
||||
public ZuulRoute(String text) {
|
||||
String location = null;
|
||||
|
||||
@@ -59,14 +59,37 @@ public class ProxyRouteLocatorTests {
|
||||
routeLocator.getRoutes(); // force refresh
|
||||
ProxyRouteSpec route = routeLocator.getMatchingRoute("/proxy/foo/1");
|
||||
assertEquals("foo", route.getLocation());
|
||||
assertEquals("/1", route.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMatchingPathWithNoPrefixStripping() throws Exception {
|
||||
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
|
||||
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**", "foo", null, false));
|
||||
this.properties.setStripPrefix(false);
|
||||
this.properties.setPrefix("/proxy");
|
||||
routeLocator.getRoutes(); // force refresh
|
||||
ProxyRouteSpec route = routeLocator.getMatchingRoute("/proxy/foo/1");
|
||||
assertEquals("foo", route.getLocation());
|
||||
assertEquals("/proxy/foo/1", route.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMatchingPathWithPrefixStripping() throws Exception {
|
||||
public void testGetMatchingPathWithLocalPrefixStripping() throws Exception {
|
||||
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
|
||||
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
|
||||
this.properties.setStripPrefix(true);
|
||||
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**", "foo"));
|
||||
this.properties.setStripPrefix(false);
|
||||
this.properties.setPrefix("/proxy");
|
||||
routeLocator.getRoutes(); // force refresh
|
||||
ProxyRouteSpec route = routeLocator.getMatchingRoute("/proxy/foo/1");
|
||||
assertEquals("foo", route.getLocation());
|
||||
assertEquals("/proxy/1", route.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMatchingPathWithGlobalPrefixStripping() throws Exception {
|
||||
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
|
||||
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**", "foo", null, false));
|
||||
this.properties.setPrefix("/proxy");
|
||||
routeLocator.getRoutes(); // force refresh
|
||||
ProxyRouteSpec route = routeLocator.getMatchingRoute("/proxy/foo/1");
|
||||
|
||||
@@ -21,17 +21,17 @@ public class SampleZuulProxyApplication {
|
||||
throw new RuntimeException("myerror");
|
||||
}
|
||||
|
||||
@RequestMapping("/local/self")
|
||||
@RequestMapping("/local")
|
||||
public String local() {
|
||||
return "Hello local";
|
||||
}
|
||||
|
||||
@RequestMapping(value="/local/self/{id}", method=RequestMethod.DELETE)
|
||||
@RequestMapping(value="/local/{id}", method=RequestMethod.DELETE)
|
||||
public String delete() {
|
||||
return "Deleted!";
|
||||
}
|
||||
|
||||
@RequestMapping(value="/local/self/{id}", method=RequestMethod.GET)
|
||||
@RequestMapping(value="/local/{id}", method=RequestMethod.GET)
|
||||
public String get() {
|
||||
return "Gotten!";
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class PreDecorationFilterTests {
|
||||
properties.setPrefix("/api");
|
||||
properties.setStripPrefix(true);
|
||||
request.setRequestURI("/api/foo/1");
|
||||
routeLocator.addRoute("/foo/**", "foo");
|
||||
routeLocator.addRoute(new ZuulRoute("/foo/**", "foo", null, false));
|
||||
filter.run();
|
||||
RequestContext ctx = RequestContext.getCurrentContext();
|
||||
assertEquals("/foo/1", ctx.get("requestURI"));
|
||||
@@ -69,7 +69,7 @@ public class PreDecorationFilterTests {
|
||||
properties.setPrefix("/api");
|
||||
properties.setStripPrefix(true);
|
||||
request.setRequestURI("/api/foo/1");
|
||||
routeLocator.addRoute(new ZuulRoute("/foo/**", "foo", null, true));
|
||||
routeLocator.addRoute("/foo/**", "foo");
|
||||
filter.run();
|
||||
RequestContext ctx = RequestContext.getCurrentContext();
|
||||
assertEquals("/1", ctx.get("requestURI"));
|
||||
|
||||
Reference in New Issue
Block a user