文档章节

ZuulFilter的order小结

go4it
 go4it
发布于 2017/05/31 00:12
字数 785
阅读 280
收藏 0

##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


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

输入图片说明

© 著作权归作者所有

共有 人打赏支持
go4it
粉丝 70
博文 817
码字总数 688180
作品 0
深圳
私信 提问
【SpringCloud NetFlix】网关Zuul(四)功能进阶

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zlt995768025/article/details/81708382 数字越小,优先级越高 自定义过滤器 shouldFilter方法 优先级 自定义...

周丽同
08/15
0
0
Springcloud+ZuulFilter微服务中过滤器的实现

1.简介: Zuul作为网关的中一个重要功能,就是实现请求的鉴定权限。我们是通过Zuul提供的过滤器来实现的。 2.ZuulFilter: ZuulFilter是过滤器的顶级父类。 他定义了四个方法: 下面让我来一一详...

全世界最好的肥猪精
12/08
0
0
springCloud(15):使用Zuul构建微服务网关-Header与文件上传和过滤器

一、Header 1.1、敏感header的设置 一般来说,可在同一个系统中的服务之间共享Header,不过应尽量防止让一些敏感的Header外泄。 zuul: routes: provide-user: sensitive-headers: Cookie,Se...

我爱大金子
2017/08/23
0
0
微服务架构网关接口设计

近年来微服务架构盛行,我司也利用spring cloud实践微服务。使用的也是spring cloud很经典的架构,zuul充当网关路由,configserver作为静态配置中心,feign作为远程调用http client 等,反正...

数齐
01/01
0
0
mysql 使用小结

某日,在使用order by 时发现结果并不是目标,找了些资料才发现,字段类型为varchar类型,需要将其转换为int类型才会得到最终结果,以下是种方法:order by varchar类型字段+0,或 order by...

道酬勤
2015/10/18
5
0

没有更多内容

加载失败,请刷新页面

加载更多

java框架学习日志2

上篇文章(java框架学习日志-1)虽然跟着写了例子,也理解为什么这么写,但是有个疑问,为什么叫控制反转?控制的是什么?反转又是什么? 控制其实就是控制对象的创建。 反转与正转对应,正转...

白话
8分钟前
0
0
Integer使用双等号比较会发生什么

话不多说,根据以下程序运行,打印的结果为什么不同? Integer a = 100;Integer b = 100;System.out.println(a == b);//print : trueInteger a = 200;Integer b = 200;System.out.pr...

兜兜毛毛
昨天
5
0
CockroachDB

百度云上的CockroachDB 云数据库 帮助文档 > 产品文档 > CockroachDB 云数据库 > 产品描述 开源NewSQL – CockroachDB在百度内部的应用与实践 嘉宾演讲视频及PPT回顾:http://suo.im/5bnORh ...

miaojiangmin
昨天
4
0
I2C EEPROM驱动实例分析

上篇分析了Linux Kernel中的I2C驱动框架,本篇举一个具体的I2C设备驱动(eeprom)来对I2C设备驱动有个实际的认识。 s3c24xx系列集成了一个基于I2C的eeprom设备at24cxx系列。at24cxx系列芯片包...

yepanl
昨天
5
0
设计模式之工厂模式

本篇博文主要翻译这篇文章: https://www.journaldev.com/1392/factory-design-pattern-in-java 由于翻译水平有限,自认为许多地方翻译不恰当,欢迎各位给出宝贵的建议,建议大家去阅读原文。...

firepation
昨天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部