pre过滤器——PreDecorationFilter

PreDecorationFilter

PreDecorationFilter属于pre最重要的过滤器,基本的路由转发配置,请求修饰都在这里完成。

执行条件:

RequestContext的实例中不包含"forward.to"并且不包含“serviceId”时执行

实际上这2个值都是此过滤器执行后才会添加到RequestContext的实例中;一般情况下正常请求中是不带这2个参数的

所以此过滤器的执行条件是:已经被此过滤器处理过的请求不会再次处理

/***/
public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        return !ctx.containsKey("forward.to") && !ctx.containsKey("serviceId");
    }

 接下来我们进入run方法了解具体的执行逻辑。

/***/
public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        /**使用UrlPathHelper处理请求参数中的url*/
        String requestURI = this.urlPathHelper.getPathWithinApplication(ctx.getRequest());
        /**根据url与配置信息做匹配,找到对应的路由route;路由规则匹配*/
        Route route = this.routeLocator.getMatchingRoute(requestURI);
        String location;
        String xforwardedfor;
        String remoteAddr;
        /**判断是否配有路由*/
        if (route != null) {
            /**获取路由的地址:服务名或真实物理地址*/
            location = route.getLocation();
            /**path:配置中表示请求的匹配路径*/
            if (location != null) {
                ctx.put("requestURI", route.getPath());
                ctx.put("proxy", route.getId());
                /**判断是否添加敏感头信息*/
                if (!route.isCustomSensitiveHeaders()) {
                    this.proxyRequestHelper.addIgnoredHeaders((String[])this.properties.getSensitiveHeaders().toArray(new String[0]));
                } else {
                /***/   
            this.proxyRequestHelper.addIgnoredHeaders((String[])route.getSensitiveHeaders().toArray(new String[0])); } /**判断是否重试*/ if (route.getRetryable() != null) { ctx.put("retryable", route.getRetryable()); } /**判断路由地址是服务名还是真实物理地址*/ if (!location.startsWith("http:") && !location.startsWith("https:")) { /**是否是转发*/ if (location.startsWith("forward:")) { ctx.set("forward.to", StringUtils.cleanPath(location.substring("forward:".length()) + route.getPath())); ctx.setRouteHost((URL)null); return null; } /***/ ctx.set("serviceId", location); ctx.setRouteHost((URL)null); ctx.addOriginResponseHeader("X-Zuul-ServiceId", location); } else { ctx.setRouteHost(this.getUrl(location)); ctx.addOriginResponseHeader("X-Zuul-Service", location); } /**是否添加代理的头信息*/ if (this.properties.isAddProxyHeaders()) { this.addProxyHeaders(ctx, route); xforwardedfor = ctx.getRequest().getHeader("X-Forwarded-For"); remoteAddr = ctx.getRequest().getRemoteAddr(); /***/ if (xforwardedfor == null) { xforwardedfor = remoteAddr; } else if (!xforwardedfor.contains(remoteAddr)) { xforwardedfor = xforwardedfor + ", " + remoteAddr; } ctx.addZuulRequestHeader("X-Forwarded-For", xforwardedfor); } /***/ if (this.properties.isAddHostHeader()) { ctx.addZuulRequestHeader("Host", this.toHostHeader(ctx.getRequest())); } } } else { /**Route为null,进行相应的fallback处理*/ log.warn("No route found for uri: " + requestURI); xforwardedfor = this.dispatcherServletPath; if (RequestUtils.isZuulServletRequest()) { log.debug("zuulServletPath=" + this.properties.getServletPath()); location = requestURI.replaceFirst(this.properties.getServletPath(), ""); log.debug("Replaced Zuul servlet path:" + location); } else { log.debug("dispatcherServletPath=" + this.dispatcherServletPath); location = requestURI.replaceFirst(this.dispatcherServletPath, ""); log.debug("Replaced DispatcherServlet servlet path:" + location); } if (!location.startsWith("/")) { location = "/" + location; } /***/ remoteAddr = xforwardedfor + location; remoteAddr = remoteAddr.replaceAll("//", "/"); ctx.set("forward.to", remoteAddr); } return null; }

从上可以,看出,preDecorationFilter主要是做路由转发前的配置信息,将配置文件中的信息提取出来添加到请求域RequestContext中。

preDecorationFilter首先做的就是路由规则的匹配Route route = this.routeLocator.getMatchingRoute(requestURI);

然后就是根据配置文件配置的信息进行相应的处理。

 

posted @ 2019-04-02 10:57  龟速前进  阅读(1762)  评论(0编辑  收藏  举报