文档章节

ZuulFilter的order小结

go4it
 go4it
发布于 2017/05/31 00:12
字数 785
阅读 150
收藏 0
点赞 0
评论 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
粉丝 51
博文 668
码字总数 465432
作品 0
深圳
深入理解Zuul之源码解析

转载请标明出处: http://blog.csdn.net/forezp/article/details/76211680 本文出自方志朋的博客 Zuul 架构图 在zuul中, 整个请求的过程是这样的,首先将请求给zuulservlet处理,zuulservl...

forezp
2017/07/27
0
0
基于docker部署的微服务架构(三): 服务网关

前言 在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个公共网关根据请求的url,路由到相应的服务。在网关中可以做一些服务调用的前置处理,比如权限验证。也可以通过动态路由,...

月冷X心寒
2016/11/18
709
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
【微服务】之七:轻松搞定SpringCloud微服务-API权限控制

【微服务】之七:轻松搞定SpringCloud微服务-API权限控制 Harries Blog™2017-12-210 阅读 httpSpringAppcatbeanAPIhttps 【微服务】轻松搞定SpringCloud微服务 目录 本系列为连载 文章 ,阅...

Harries Blog™
2017/12/21
0
0
说说MySQL ORDER BY

导读 在MySQL里,ORDER BY可以有几种玩法? 先看下手册里的说明: 也就是,有三种ORDER BY模式,下面分别简单演示下。 测试表: 例1. 按指定列名ORDER BY 例2. 按指定序号的列排序 例3. 根据...

老叶茶馆
02/12
0
0
springboot使用zuul

配置pom zuul依赖 启用zuul application.yaml 其中,使用listOfServers可以配置外部服务的多个负载均衡;使用forward可以forward到外部地址,也可以forward内部的相对地址。 配置filter docs...

go4it
2016/10/24
159
0
mysql 使用小结

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

道酬勤
2015/10/18
5
0
小谈pointer和relation

在apicloud的数据库中,pointer和relation是在很难让人理解。 通过不断的实践,终于有点明白了。 pointer和relation作用:在nosql数据库中实现表之间的关联 首先来说说pointer 官方文档上说“...

达斯雷马
2016/12/08
95
0
leetcode算法题解(Java版)-1-二叉树遍历

又开始刷算法题了,正好在学Java,顺便也练练Java。 题目描述 Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right......

kissjz
04/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

spring boot中swagger2使用

1.pom.xml中添加 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version>......

说回答
5分钟前
0
0
tomcat虚拟路径的几种配置方法

tomcat虚拟路径的几种配置方法 一般我们都是直接引用webapps下面的web项目,如果我们要部署一个在其它地方的WEB项目,这就要在TOMCAT中设置虚拟路径了,Tomcat的加载web顺序是先加载 $Tomcat_ho...

Helios51
17分钟前
1
0
Mac 安装jupyter notebook的过程

MAC台式机 python:mac下自带Python 2.7.10 1.先升级了pip安装工具:sudo python -m pip install --upgrade --force pip 2.安装setuptools 工具:sudo pip install setuptools==33.1.1 3.安装......

火力全開
23分钟前
0
0
导航守卫解释与例子

“导航”表示路由正在发生改变。 正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。 记住...

tianyawhl
23分钟前
0
0
Java日志框架-logback配置文件多环境日志配置(开发、测试、生产)(原始解决方法)

说明:这种方式应该算是最通用的,原理是通过判断标签实现。 <!-- if-then form --> <if condition="some conditional expression"> <then> ... </then> </if> ......

浮躁的码农
37分钟前
1
0
FTP传输时的两种登录方式和区别

登录方式 匿名登录 用户名为: anonymous。 密码为:任何合法 email 地址。 授权登录 用户名为:用户在远程系统中的用户帐号。 密码为:用户在远程系统中的用户密码。 区别 匿名登录 只能访问...

寰宇01
38分钟前
0
0
plsql developer 配置监听(不安装oracle客户端)

plsql developer 配置监听(不安装oracle客户端)

微小宝
45分钟前
1
0
数据库(分库分表)中间件对比

本人的宗旨就是,能copy的,绝对不手写。 分区:对业务透明,分区只不过把存放数据的文件分成了许多小块,例如mysql中的一张表对应三个文件.MYD,MYI,frm。 根据一定的规则把数据文件(MYD)和索...

奔跑吧代码
49分钟前
2
0
Netty与Reactor模式详解

在学习Reactor模式之前,我们需要对“I/O的四种模型”以及“什么是I/O多路复用”进行简单的介绍,因为Reactor是一个使用了同步非阻塞的I/O多路复用机制的模式。 I/O的四种模型 I/0 操作 主要...

hutaishi
55分钟前
1
0
【2018.07.16学习笔记】【linux高级知识 20.16-20.19】

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析

lgsxp
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部