Spring-cloud-netflix: How to change service path in Zuul route

Created on 26 Apr 2017  路  8Comments  路  Source: spring-cloud/spring-cloud-netflix

I am using Zuul to make a URL appear to be part of an existing API when it is really serviced by a different microservice. So I want to make this route to use the route conventions of one service, but then match paths on the underlying microservice.

I want to route /api/v1/pathForGateway/** to /api/microservicePath/** on the micro service. An example full endpoint could be /api/v1/pathForGateway/function1, and it would map to the microservice at this full endpoint /api/microservicePath/function1.

Conceptually what I need is to strip the prefix, but then add a new prefix.

This is using Eureka Service Discovery, so I can't use uri.

zuul.routes.servicea.path=/api/v1/pathForGateway/**
zuul.routes.servicea.serviceId=microservice-a
zuul.routes.servicea.stripPrefix=true
# Is there a configuration like this?
zuul.routes.servicea.appendPrefix=/api/microservicePath/
question

Most helpful comment

That was a great suggestion @spencergibb.

For future reference, this setup works well.

@Component
public class CustomPathZuulFilter extends ZuulFilter
{
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return PreDecorationFilter.FILTER_ORDER + 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        Object originalRequestPath = context.get(REQUEST_URI_KEY);
        String modifiedRequestPath = "/api/microservicePath" + originalRequestPath;
        context.put(REQUEST_URI_KEY, modifiedRequestPath);

        return null;
    }
}

application.properties:

zuul.routes.servicea.path=/api/v1/pathForGateway/**
zuul.routes.servicea.serviceId=microservice-a
zuul.routes.servicea.stripPrefix=true

All 8 comments

There's not really a way to do this with configuration. You'd need to write a custom filter.

That sounds reasonable. So I'd like to write a custom filter that builds on the existing routing filter. But, would just append the path. How can I write a custom routing filter that builds on the underlying filter?

That was a great suggestion @spencergibb.

For future reference, this setup works well.

@Component
public class CustomPathZuulFilter extends ZuulFilter
{
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return PreDecorationFilter.FILTER_ORDER + 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        Object originalRequestPath = context.get(REQUEST_URI_KEY);
        String modifiedRequestPath = "/api/microservicePath" + originalRequestPath;
        context.put(REQUEST_URI_KEY, modifiedRequestPath);

        return null;
    }
}

application.properties:

zuul.routes.servicea.path=/api/v1/pathForGateway/**
zuul.routes.servicea.serviceId=microservice-a
zuul.routes.servicea.stripPrefix=true

shouldFilter() should probably only return true if the path matches. Good job, BTW.

Hi. I need to do something like @dlvenable but replace the whole path instead of part of the path. My intent is to be able to take an endpoint, such as /hello1, and route a certain percentage of the traffic to /hello2.

For example, let's say in Zuul, I mapped the endpoint, /hello, to go to /hello1. My application.yml looks this:
zuul:
routes:
hellohello:
path: /hello/**
url: http://localhost:8080/hello1

Then I have a prefilter that has a run method like so:
public static final String REQUEST_URI_KEY = "requestURI";

@Override
public Object run() {
final RequestContext context = RequestContext.getCurrentContext();
String modifiedPath = "/hello2";
context.put(REQUEST_URI_KEY, modifiedPath);
return null;
}

When I run a curl command: curl localhost:8080/hello
{"timestamp":1509505655531,"status":404,"error":"Not Found","message":"No message available","path":"/hello1/hello2"}

It seems that "/hello2" is being appended to the "/hello1".

How can I have it forward to "/hello2"?

Thanks in advance.

You could also do this by using a forward, e.g.

    service:
      path: /some/path
      url: forward:/your/changed/path

    other-service:
      path: /your/changed/path/**
      serviceId: downstream-service

i have tried as blow configuration but not working for me.
zuul:
routes:

CSRFToken:
  path: /**/CSRFTokentest
  url:  forward:/api/public/CSRFToken
  MyCSRFToken:
    path: /**/CSRFToken
    url:  http://<ipaddress>:8080
    stripPrefix: false
    ribbon:
      eureka:
        enabled: false
Was this page helpful?
0 / 5 - 0 ratings