博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊spring cloud gateway的ForwardedHeadersFilter
阅读量:5768 次
发布时间:2019-06-18

本文共 5291 字,大约阅读时间需要 17 分钟。

本文主要研究一下spring cloud gateway的ForwardedHeadersFilter

GatewayAutoConfiguration

spring-cloud-gateway-core-2.0.0.RC1-sources.jar!/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java

@Configuration@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)@EnableConfigurationProperties@AutoConfigureBefore(HttpHandlerAutoConfiguration.class)@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})@ConditionalOnClass(DispatcherHandler.class)public class GatewayAutoConfiguration {	//......	@Bean	@ConditionalOnProperty(name = "spring.cloud.gateway.forwarded.enabled", matchIfMissing = true)	public ForwardedHeadersFilter forwardedHeadersFilter() {		return new ForwardedHeadersFilter();	}	//......}复制代码

ForwardedHeadersFilter

spring-cloud-gateway-core-2.0.0.RC1-sources.jar!/org/springframework/cloud/gateway/filter/headers/ForwardedHeadersFilter.java

public class ForwardedHeadersFilter implements HttpHeadersFilter, Ordered {	public static final String FORWARDED_HEADER = "Forwarded";	@Override	public int getOrder() {		return 0;	}	@Override	public HttpHeaders filter(HttpHeaders input, ServerWebExchange exchange) {		ServerHttpRequest request = exchange.getRequest();		HttpHeaders original = input;		HttpHeaders updated = new HttpHeaders();		// copy all headers except Forwarded		original.entrySet().stream()				.filter(entry -> !entry.getKey().toLowerCase().equalsIgnoreCase(FORWARDED_HEADER))				.forEach(entry -> updated.addAll(entry.getKey(), entry.getValue()));		List
forwardeds = parse(original.get(FORWARDED_HEADER)); for (Forwarded f : forwardeds) { updated.add(FORWARDED_HEADER, f.toString()); } //TODO: add new forwarded URI uri = request.getURI(); String host = original.getFirst(HttpHeaders.HOST); Forwarded forwarded = new Forwarded() .put("host", host) .put("proto", uri.getScheme()); InetSocketAddress remoteAddress = request.getRemoteAddress(); if (remoteAddress != null) { String forValue = remoteAddress.getAddress().getHostAddress(); int port = remoteAddress.getPort(); if (port >= 0) { forValue = forValue + ":" + port; } forwarded.put("for", forValue); } // TODO: support by? updated.add(FORWARDED_HEADER, forwarded.toHeaderValue()); return updated; } /* for testing */ static List
parse(List
values) { ArrayList
forwardeds = new ArrayList<>(); if (CollectionUtils.isEmpty(values)) { return forwardeds; } for (String value : values) { Forwarded forwarded = parse(value); forwardeds.add(forwarded); } return forwardeds; } /* for testing */ static Forwarded parse(String value) { String[] pairs = StringUtils.tokenizeToStringArray(value, ";"); LinkedCaseInsensitiveMap
result = splitIntoCaseInsensitiveMap(pairs); if (result == null) return null; Forwarded forwarded = new Forwarded(result); return forwarded; } @Nullable /* for testing */ static LinkedCaseInsensitiveMap
splitIntoCaseInsensitiveMap(String[] pairs) { if (ObjectUtils.isEmpty(pairs)) { return null; } LinkedCaseInsensitiveMap
result = new LinkedCaseInsensitiveMap<>(); for (String element : pairs) { String[] splittedElement = StringUtils.split(element, "="); if (splittedElement == null) { continue; } result.put(splittedElement[0].trim(), splittedElement[1].trim()); } return result; }}复制代码

这个filter首先拷贝了请求的header,然后将请求中的Forwarded提取出来,解析成一个个Forwarded对象,添加到新的HttpHeaders中。除此之外,还补充了一个转发信息的Forwarded(host,proto,for)

Forwarded

语法

Forwarded: by=
; for=
; host=
; proto=
复制代码
  • by= 该请求进入到代理服务器的接口。
  • for= 发起请求的客户端以及代理链中的一系列的代理服务器。
  • host= 代理接收到的 Host首部的信息。
  • proto=<http|https> 表示发起请求时采用的何种协议(通常是 "http" 或者 "https")。

实例

Forwarded: for=192.0.2.60; proto=http; by=203.0.113.43Forwarded: proto=http;host="localhost:10000";for="0:0:0:0:0:0:0:1:56443"复制代码

对象

static class Forwarded {		private static final char EQUALS = '=';		private static final char SEMICOLON = ';';		private final Map
values; public Forwarded() { this.values = new HashMap<>(); } public Forwarded(Map
values) { this.values = values; } public Forwarded put(String key, String value) { this.values.put(key, quoteIfNeeded(value)); return this; } private String quoteIfNeeded(String s) { if (s.contains(":")) { //TODO: broaded quote return "\""+s+"\""; } return s; } public String get(String key) { return this.values.get(key); } /* for testing */ Map
getValues() { return this.values; } @Override public String toString() { return "Forwarded{" + "values=" + this.values + '}'; } public String toHeaderValue() { StringBuilder builder = new StringBuilder(); for (Map.Entry
entry : this.values.entrySet()) { if (builder.length() > 0) { builder.append(SEMICOLON); } builder.append(entry.getKey()) .append(EQUALS) .append(entry.getValue()); } return builder.toString(); } }复制代码

小结

RFC 7239(June 2014)提出了一个标准化的Forwarded头部,来携带反向代理的基本信息,用于替代X-Forwarded系列及X-Real-IP等非标准化的头部。而ForwardedHeadersFilter便是提供了Forwarded头部的转发支持,目前经过gateway的请求会带上一个转发信息的Forwarded(host,proto,for)。

doc

转载地址:http://bfbux.baihongyu.com/

你可能感兴趣的文章
堆栈和托管堆 c#
查看>>
如何清除swap里的文件
查看>>
android 一些常用权限
查看>>
asp.net的各种缓存【转】
查看>>
HDU 6071 Lazy Running (同余最短路 dij)
查看>>
还需要添加的chrome插件
查看>>
js正则积累
查看>>
利用java实现可远程执行linux命令的小工具
查看>>
C#环境变量配置及csc命令详解(转自cy88310)
查看>>
KMP - 简单应用
查看>>
PHP学习之语法基础篇
查看>>
生成tli tlh 文件
查看>>
static和extern的用法小结
查看>>
Python - 发送邮件
查看>>
WPF学习01——新的图形引擎DirectX
查看>>
OpenCV学习(34) 点到轮廓的距离
查看>>
信息安全实验一:buffer-overflow
查看>>
[leetcode-657-Judge Route Circle]
查看>>
js回忆总结
查看>>
UVA 1590 IP Networks JAVA
查看>>