文档章节

聊聊spring cloud的PreserveHostHeaderGatewayFilter

go4it
 go4it
发布于 06/14 22:11
字数 440
阅读 25
收藏 0

本文主要研究下spring cloud gateway的PreserveHostHeaderGatewayFilter

GatewayAutoConfiguration

spring-cloud-gateway-core-2.0.0.RC2-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
	public PreserveHostHeaderGatewayFilterFactory preserveHostHeaderGatewayFilterFactory() {
		return new PreserveHostHeaderGatewayFilterFactory();
	}
    //......
}

PreserveHostHeaderGatewayFilterFactory

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

public class PreserveHostHeaderGatewayFilterFactory extends AbstractGatewayFilterFactory {

	public GatewayFilter apply() {
		return apply(o -> {});
	}

    public GatewayFilter apply(Object config) {
		return (exchange, chain) -> {
			exchange.getAttributes().put(PRESERVE_HOST_HEADER_ATTRIBUTE, true);
			return chain.filter(exchange);
		};
	}
}

这个filter超级简单,就往exchange添加PRESERVE_HOST_HEADER_ATTRIBUTE,设置为true

NettyRoutingFilter

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java

public class NettyRoutingFilter implements GlobalFilter, Ordered {

	private final HttpClient httpClient;
	private final ObjectProvider<List<HttpHeadersFilter>> headersFilters;

	public NettyRoutingFilter(HttpClient httpClient,
			ObjectProvider<List<HttpHeadersFilter>> headersFilters) {
		this.httpClient = httpClient;
		this.headersFilters = headersFilters;
	}

	@Override
	public int getOrder() {
		return Ordered.LOWEST_PRECEDENCE;
	}

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);

		String scheme = requestUrl.getScheme();
		if (isAlreadyRouted(exchange) || (!"http".equals(scheme) && !"https".equals(scheme))) {
			return chain.filter(exchange);
		}
		setAlreadyRouted(exchange);

		ServerHttpRequest request = exchange.getRequest();

		final HttpMethod method = HttpMethod.valueOf(request.getMethod().toString());
		final String url = requestUrl.toString();

		HttpHeaders filtered = filterRequest(this.headersFilters.getIfAvailable(),
				exchange);

		final DefaultHttpHeaders httpHeaders = new DefaultHttpHeaders();
		filtered.forEach(httpHeaders::set);

		String transferEncoding = request.getHeaders().getFirst(HttpHeaders.TRANSFER_ENCODING);
		boolean chunkedTransfer = "chunked".equalsIgnoreCase(transferEncoding);

		boolean preserveHost = exchange.getAttributeOrDefault(PRESERVE_HOST_HEADER_ATTRIBUTE, false);

		return this.httpClient.request(method, url, req -> {
			final HttpClientRequest proxyRequest = req.options(NettyPipeline.SendOptions::flushOnEach)
					.headers(httpHeaders)
					.chunkedTransfer(chunkedTransfer)
					.failOnServerError(false)
					.failOnClientError(false);

			if (preserveHost) {
				String host = request.getHeaders().getFirst(HttpHeaders.HOST);
				proxyRequest.header(HttpHeaders.HOST, host);
			}

			return proxyRequest.sendHeaders() //I shouldn't need this
					.send(request.getBody().map(dataBuffer ->
							((NettyDataBuffer)dataBuffer).getNativeBuffer()));
		}).doOnNext(res -> {
			ServerHttpResponse response = exchange.getResponse();
			// put headers and status so filters can modify the response
			HttpHeaders headers = new HttpHeaders();
			
			res.responseHeaders().forEach(entry -> headers.add(entry.getKey(), entry.getValue()));

			HttpHeaders filteredResponseHeaders = HttpHeadersFilter.filter(
					this.headersFilters.getIfAvailable(), headers, exchange, Type.RESPONSE);
			
			response.getHeaders().putAll(filteredResponseHeaders);
			HttpStatus status = HttpStatus.resolve(res.status().code());
			if (status != null) {
				response.setStatusCode(status);
			} else if (response instanceof AbstractServerHttpResponse) {
				// https://jira.spring.io/browse/SPR-16748
				((AbstractServerHttpResponse) response).setStatusCodeValue(res.status().code());
			} else {
				throw new IllegalStateException("Unable to set status code on response: " +res.status().code()+", "+response.getClass());
			}

			// Defer committing the response until all route filters have run
			// Put client response as ServerWebExchange attribute and write response later NettyWriteResponseFilter
			exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
		}).then(chain.filter(exchange));
	}
}

这里从读取PRESERVE_HOST_HEADER_ATTRIBUTE属性,没有则默认false。如果为true,则proxyRequest.header(HttpHeaders.HOST, host),传递host头部。

小结

PreserveHostHeaderGatewayFilter就是在gateway转发请求的时候把原始请求的host头部带上,转发给目标服务。默认该filter是启用的。

doc

© 著作权归作者所有

共有 人打赏支持
go4it
粉丝 51
博文 699
码字总数 501216
作品 0
深圳
聊聊spring cloud gateway的GatewayFilter

序 本文主要研究一下spring cloud gateway的GatewayFilter GatewayFilter spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/GatewayFilter.jav......

go4it
06/09
0
0
聊聊spring.cloud.gateway.default-filters

序 本文主要研究下spring.cloud.gateway.default-filters 配置 default-filters,配置的是FilterDefinition对象 FilterDefinition spring-cloud-gateway-core-2.0.0.RC1-sources.jar!/org/sp......

go4it
06/01
0
0
聊聊spring cloud netflix的HystrixCommands

序 本文主要研究一下spring cloud netflix的HystrixCommands。 maven 这个组件对hystrix进行了封装了,2.0.0.RELEASE全面支持了Reactor的Reactive Streams。 spring-cloud-starter-netflix-h...

go4it
06/22
0
0
聊聊eureka client的shutdown

序 本文主要研究一下eureka client的shutdown EurekaRegistration spring-cloud-netflix-eureka-client-2.0.0.RC1-sources.jar!/org/springframework/cloud/netflix/eureka/EurekaClientAuto......

go4it
05/04
0
0
聊聊ribbon的超时时间设置

序 本文主要研究一下ribbon的超时时间设置 配置 实例 RibbonClientConfiguration spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/Ribb......

go4it
07/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Zookeeper总结

Zookeeper的部分概念 什么是zookeeeper? Zookeeper是一个分布式服务的协调中心 zookeeper节点的角色类型? Leader(领导者)、Follower(跟随者)、Observer(观察者) Leader 负责更新系统...

DemonsI
9分钟前
0
0
Redis学习笔记

常用命令 从Docker进入Redis的命令 sudo docker exec -it redis /bin/bash

OSC_fly
10分钟前
0
0
SqlServer查询某个日期的数据

select * from View_ZJMONITORINGCORROSION where ENTERDATE > CONVERT(datetime,DATEADD(day,1,'2017/12/28 14:53:07'))...

笑丶笑
11分钟前
0
0
常用编码规范

Standard characters https://ascii.cl/

yeahlife
13分钟前
0
0
flannel实战

docker swarm mode的出现是个里程碑,官方原生的编排调度看起来都成雏形了,但是swarm mode和容器外部系统的对接、网络性能始终不尽人意,swarm mode下各种开源周边不能使用,感觉swarm mod...

China_OS
14分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部