【问题标题】:How to do URL Rewrite in Zuul Proxy?如何在 Zuul Proxy 中进行 URL 重写?
【发布时间】:2015-08-05 10:24:29
【问题描述】:

我的 Zuul 过滤器收到的请求之一是 URI /hello/World,我想将其重定向到 /myapp/test 。这个 /myapp/test 是在 Eureka 中注册的服务。

zuul:
  routes:
     xyz:
         path: /hello/World
         url: http://localhost:1234/myapp/test
         stripPrefix: true

当我尝试上述配置时,传入的 URI 会以配置的 URL 为后缀,例如 http://localhost:1234/myapp/test/World 。我遇到的几个链接似乎表明 Zuul 中还没有 URL 重写功能。

在 Zuul 层有没有其他方法可以做到这一点?

注意:此时,我无法在 Web 服务器或任何其他层中执行此反向代理,因为我的 Zuul 过滤器是直接接收请求的过滤器。

【问题讨论】:

  • 看起来 Zuul 没有 URL Rewrite 功能,因此我们在它前面配置了 Nginx 来进行 URL 重写。

标签: url-rewriting rewrite netflix-zuul


【解决方案1】:

使用@Adelin 解决方案,几乎没有改进

使用 'url' 属性作为自定义 Url 重写的前置路径(我在示例中禁用了 Eureka):

ribbon.eureka.enabled=false

zuul.routes.route1.path=/route1/**
zuul.routes.route1.serviceId=service1
zuul.routes.route1.url=/path/to/prepend

service1.ribbon.listOfServers=http://server1

然后实现以下过滤器:

/**
 * Fixing missing URL rewriting when using ribbon
 */
@Component
public class CustomPathZuulFilter extends ZuulFilter {

    @Autowired
    private ZuulProperties zuulProperties;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
    }

    @Override
    public boolean shouldFilter() {
        // override PreDecorationFilter only if executed previously successfully
        return RequestContext.getCurrentContext().getFilterExecutionSummary().toString()
                .contains("PreDecorationFilter[SUCCESS]");
    }

    @Override
    public Object run() {
        final RequestContext context = RequestContext.getCurrentContext();
        if (context.get(FilterConstants.SERVICE_ID_KEY) == null || context.getRouteHost() != null) {
            // not a Ribbon route
            return null;
        }

        // get current ZuulRoute
        final String proxy = (String) context.get(FilterConstants.PROXY_KEY);
        final ZuulRoute zuulRoute = this.zuulProperties.getRoutes().get(proxy);

        // patch URL by prefixing it with zuulRoute.url
        final Object originalRequestPath = context.get(FilterConstants.REQUEST_URI_KEY);
        final String modifiedRequestPath = zuulRoute.getUrl() + originalRequestPath;
        context.put(FilterConstants.REQUEST_URI_KEY, modifiedRequestPath);

        // patch serviceId because :
        // - has been set to route.location in PreDecorationFilter
        // - route.location has been set to zuulRoute.location in SimpleRouteLocator
        // - zuulRoute.location return zuulRoute.url if set
        context.set(FilterConstants.SERVICE_ID_KEY, zuulRoute.getServiceId());

        return null;
    }
}

现在对 /route1 的调用将被代理到 http://server1/path/to/prepend

此解决方案还与不使用 Ribbon 的共存路由兼容。

不使用 Ribbon 的共存路由示例:

zuul.routes.route2.path=/route2/**
zuul.routes.route2.url=http://server2/some/path

/route2 的调用将由 SimpleHostRoutingFilter 代理到 http://server2/some/path(如果未禁用)

【讨论】:

    【解决方案2】:

    这是@Vikash 链接中发布的解决方案

    @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;
        }
    }
    

    【讨论】:

    • 除非@Override public String filterType() { return "route"; },否则这将不起作用
    【解决方案3】:

    您是否尝试过创建 preFilter 甚至 routeFilter ?

    这样你就可以拦截请求,改变路由。

    Zuul Filters

    【讨论】:

    • 不,但是,这是个好主意。我正在寻找可以通过配置实现的解决方案,看起来它不存在。我会尝试这种方法。谢谢
    • 我也有类似的问题要解决并关注github.com/spring-cloud/spring-cloud-netflix/issues/1893,但这也会删除您的请求参数,有没有办法也保留它们
    猜你喜欢
    • 2010-11-05
    • 2010-10-06
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 2021-03-04
    相关资源
    最近更新 更多