ZuulFilter的order小结

##filters org/springframework/cloud/netflix/zuul/filters/

##pre |filter|type|order|desc| |:---|:---| :----|:----| |ServletDetectionFilter|pre| -3 |Detects whether a request is ran through the {@link DispatcherServlet} or {@link ZuulServlet}.The purpose was to detect this up-front at the very beginning of Zuul filter processing and rely on this information in all filters.RequestContext is used such that the information is accessible to classes which do not have a request reference.| |Servlet30WrapperFilter|pre| -2 |zuul适配servlet request| |FormBodyWrapperFilter| pre | -1 | 将上下文中ZuulRequestHeaders的content-type设置成了带文件类型+boundary的形式.| |DebugFilter| pre | 1 |debug路由标识| |PreDecorationFilter|pre| 5 |补充头信息,比如是有路由配置的,则添加proxy标识为路由id,对于非http,https以及不是forward的标识serviceId|

##post |filter|type|order|desc| |:---|:---| :----|:----| |SendErrorFilter|post| 0 |当上下文内含error.status_code且没经过本filter时生效,补充上下文内error信息| |SendResponseFilter|post| 1000 |返回内容|

##route |filter|type|order|desc| |:---|:---| :----|:----| |RibbonRoutingFilter|route| 10 |在上下文中没有routeHost且sendZuulResponse为true,而且serviceId值不为空时生效.| |SimpleHostRoutingFilter|route| 100 |在上下文中存在routeHost且sendZuulResponse为true时生效| |SendForwardFilter|route| 500 |存在forward.to以及sendForwardFilter.ran为false时生效|

##PreDecorationFilter填充上下文变量 spring-cloud-netflix-core-1.2.6.RELEASE-sources.jar!/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java

public class PreDecorationFilter extends ZuulFilter {

	public static final int FILTER_ORDER = 5;

	private RouteLocator routeLocator;

	private String dispatcherServletPath;

	private ZuulProperties properties;

	private UrlPathHelper urlPathHelper = new UrlPathHelper();

	private ProxyRequestHelper proxyRequestHelper;

	public PreDecorationFilter(RouteLocator routeLocator, String dispatcherServletPath, ZuulProperties properties,
			ProxyRequestHelper proxyRequestHelper) {
		this.routeLocator = routeLocator;
		this.properties = properties;
		this.urlPathHelper.setRemoveSemicolonContent(properties.isRemoveSemicolonContent());
		this.dispatcherServletPath = dispatcherServletPath;
		this.proxyRequestHelper = proxyRequestHelper;
	}

	@Override
	public int filterOrder() {
		return FILTER_ORDER;
	}

	@Override
	public String filterType() {
		return "pre";
	}

	@Override
	public boolean shouldFilter() {
		RequestContext ctx = RequestContext.getCurrentContext();
		return !ctx.containsKey("forward.to") // a filter has already forwarded
				&& !ctx.containsKey("serviceId"); // a filter has already determined
													// serviceId
	}

	@Override
	public Object run() {
		RequestContext ctx = RequestContext.getCurrentContext();
		final String requestURI = this.urlPathHelper.getPathWithinApplication(ctx.getRequest());
		Route 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.isCustomSensitiveHeaders()) {
					this.proxyRequestHelper
							.addIgnoredHeaders(this.properties.getSensitiveHeaders().toArray(new String[0]));
				}
				else {
					this.proxyRequestHelper.addIgnoredHeaders(route.getSensitiveHeaders().toArray(new String[0]));
				}

				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);
				}
				else if (location.startsWith("forward:")) {
					ctx.set("forward.to",
							StringUtils.cleanPath(location.substring("forward:".length()) + route.getPath()));
					ctx.setRouteHost(null);
					return null;
				}
				else {
					// set serviceId for use in filters.route.RibbonRequest
					ctx.set("serviceId", location);
					ctx.setRouteHost(null);
					ctx.addOriginResponseHeader("X-Zuul-ServiceId", location);
				}
				if (this.properties.isAddProxyHeaders()) {
					addProxyHeaders(ctx, route);
					String xforwardedfor = ctx.getRequest().getHeader("X-Forwarded-For");
					String remoteAddr = ctx.getRequest().getRemoteAddr();
					if (xforwardedfor == null) {
						xforwardedfor = remoteAddr;
					}
					else if (!xforwardedfor.contains(remoteAddr)) { // Prevent duplicates
						xforwardedfor += ", " + remoteAddr;
					}
					ctx.addZuulRequestHeader("X-Forwarded-For", xforwardedfor);
				}
				if (this.properties.isAddHostHeader()) {
					ctx.addZuulRequestHeader("Host", toHostHeader(ctx.getRequest()));
				}
			}
		}
		else {
			log.warn("No route found for uri: " + requestURI);

			String fallBackUri = requestURI;
			String fallbackPrefix = this.dispatcherServletPath; // default fallback
																// servlet is
																// DispatcherServlet

			if (RequestUtils.isZuulServletRequest()) {
				// remove the Zuul servletPath from the requestUri
				log.debug("zuulServletPath=" + this.properties.getServletPath());
				fallBackUri = fallBackUri.replaceFirst(this.properties.getServletPath(), "");
				log.debug("Replaced Zuul servlet path:" + fallBackUri);
			}
			else {
				// remove the DispatcherServlet servletPath from the requestUri
				log.debug("dispatcherServletPath=" + this.dispatcherServletPath);
				fallBackUri = fallBackUri.replaceFirst(this.dispatcherServletPath, "");
				log.debug("Replaced DispatcherServlet servlet path:" + fallBackUri);
			}
			if (!fallBackUri.startsWith("/")) {
				fallBackUri = "/" + fallBackUri;
			}
			String forwardURI = fallbackPrefix + fallBackUri;
			forwardURI = forwardURI.replaceAll("//", "/");
			ctx.set("forward.to", forwardURI);
		}
		return null;
	}

	private void addProxyHeaders(RequestContext ctx, Route route) {
		HttpServletRequest request = ctx.getRequest();
		String host = toHostHeader(request);
		String port = String.valueOf(request.getServerPort());
		String proto = request.getScheme();
		if (hasHeader(request, "X-Forwarded-Host")) {
			host = request.getHeader("X-Forwarded-Host") + "," + host;
			if (!hasHeader(request, "X-Forwarded-Port")) {
				if (hasHeader(request, "X-Forwarded-Proto")) {
					StringBuilder builder = new StringBuilder();
					for (String previous : StringUtils.commaDelimitedListToStringArray(request.getHeader("X-Forwarded-Proto"))) {
						if (builder.length()>0) {
							builder.append(",");
						}
						builder.append("https".equals(previous) ? "443" : "80");
					}
					builder.append(",").append(port);
					port = builder.toString();
				}
			} else {
				port = request.getHeader("X-Forwarded-Port") + "," + port;
			}
			proto = request.getHeader("X-Forwarded-Proto") + "," + proto;
		}
		ctx.addZuulRequestHeader("X-Forwarded-Host", host);
		ctx.addZuulRequestHeader("X-Forwarded-Port", port);
		ctx.addZuulRequestHeader(ZuulHeaders.X_FORWARDED_PROTO, proto);
		addProxyPrefix(ctx, route);
	}

	private boolean hasHeader(HttpServletRequest request, String name) {
		return StringUtils.hasLength(request.getHeader(name));
	}

	private void addProxyPrefix(RequestContext ctx, Route route) {
		String forwardedPrefix = ctx.getRequest().getHeader("X-Forwarded-Prefix");
		String contextPath = ctx.getRequest().getContextPath();
		String prefix = StringUtils.hasLength(forwardedPrefix) ? forwardedPrefix
				: (StringUtils.hasLength(contextPath) ? contextPath : null);
		if (StringUtils.hasText(route.getPrefix())) {
			StringBuilder newPrefixBuilder = new StringBuilder();
			if (prefix != null) {
				if (prefix.endsWith("/") && route.getPrefix().startsWith("/")) {
					newPrefixBuilder.append(prefix, 0, prefix.length() - 1);
				}
				else {
					newPrefixBuilder.append(prefix);
				}
			}
			newPrefixBuilder.append(route.getPrefix());
			prefix = newPrefixBuilder.toString();
		}
		if (prefix != null) {
			ctx.addZuulRequestHeader("X-Forwarded-Prefix", prefix);
		}
	}

	private String toHostHeader(HttpServletRequest request) {
		int port = request.getServerPort();
		if ((port == 80 && "http".equals(request.getScheme()))
				|| (port == 443 && "https".equals(request.getScheme()))) {
			return request.getServerName();
		}
		else {
			return request.getServerName() + ":" + port;
		}
	}

	private URL getUrl(String target) {
		try {
			return new URL(target);
		}
		catch (MalformedURLException ex) {
			throw new IllegalStateException("Target URL is malformed", ex);
		}
	}
}

##doc


想获取最新资讯,请关注微信公众号

输入图片说明

转载于:https://my.oschina.net/go4it/blog/911432

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值