目录

一、背景

golanghttputilhosthostgolanghttp 503

二、排查过程

1、打印req.header

ForwardedGFS.scg.ip
(1)GFS.scg.ip
Gfs.scg.ip 是 Spring Cloud Gateway 中的一个自定义请求头部字段,用于在路由
中传递客户端的 IP 地址信息。
(2)Forwarded
在 HTTP 请求中,Forwarded 是一种标准化的请求头,用于识别原始客户端和代理之间
的连接信息。该字段的值包括一系列键值对,每个键值对都表示一个不同的属性。
goproxyheader503
req.Header = http.Header{}
req.Header.Set("traceId", traceId)
req.Header.Set("host", "XXX")

2、tcpdump抓包分析

# 抓取请求本机8080端口的请求
sudo tcpdump -i wlo1 -A  port 8080
# 抓取本机发出的http请求
sudo tcpdump -i wlo1 -A dst host 下游域名

(1)先抓取8080端口的请求,查看header差异

host: xxx # 网关不设置header的时候,host是本机ip
host: localization.xx # 网关设置header的时候,host为目标主机域名
hosthostgolanghostpythonhost
hosthostiphttppythonhost
hostgolanghost

(2)抓取目标域名请求体

1)网关没有配置header,且proxy清空header

# sudo tcpdump -i wlo1 -A dst host 下游python服务域名
......Pa.I.....P...(...POST /xxx?xxx=test HTTP/1.1
Host: 10.xx:8080
Content-Length: 3013
Traceid: f70cef79265d41be80002ab8ee10abf5
Traceparent: 00-f70cef79265d41be80002ab8ee10abf5-07f71cc5604c734a-00

2)网关配置header,且proxy清空header

# sudo tcpdump -i wlo1 -A dst host 下游python服务域名
......P!.....Q`P...(...POST /location?map_id=test HTTP/1.1
Host: 下游python服务域名
Content-Length: 3013
Traceid: 972e155927b3fcf665550ab0824acb87
Traceparent: 00-972e155927b3fcf665550ab0824acb87-627675466a61796b-7462733d667273
hostheadertcpdumphostgolangreq.Headerhostpython

3、go设置host方式

gohost
req.Host
	req.Host 是一个字符串类型的字段,表示了 HTTP 请求头部中的 Host 信息。
	如果该字段为空,则默认使用请求的目标地址(即 req.URL.Host)作为 Host 信息。
req.Header.Set("host")  # 目前使用且设置host失效
	header中的host字段。
req.URL.HOST
	request.URL.Host 是一个字符串类型的字段,表示 HTTP 请求中目标
	地址的 HOST信息,跟URL是对应的。
req.Header.Set("host")
proxy.Director = func(req *http.Request) {
		originalDirector(req)
		modifyRequest(req)
		// 添加自定义标头
		req.Header.Set("traceId", traceId)
		req.Header.Set("host", "xxx")
		log.Infof("req.Header:(%#v)", req.Header)
	}
打印结果,没有host!!!

(1)打印req.URL.HOST

req.URLurlhosthttputilrewritetargethostreq.URL.HOST
req.url:(\u0026url.URL{Scheme:\"http\", Opaque:\"\", User:(*url.Userinfo)(nil), 
Host:\"下游python服务域名\", 
Path:\"/xx\", RawPath:\"\", OmitHost:false, ForceQuery:false, 
RawQuery:\"map_id=test\", Fragment:\"\", RawFragment:\"\"}
# proxy源码
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
	director := func(req *http.Request) {
		rewriteRequestURL(req, target)
	}
	return &ReverseProxy{Director: director}
}
func rewriteRequestURL(req *http.Request, target *url.URL) {
	targetQuery := target.RawQuery
	req.URL.Scheme = target.Scheme
	req.URL.Host = target.Host
	req.URL.Path, req.URL.RawPath = joinURLPath(target, req.URL)
	if targetQuery == "" || req.URL.RawQuery == "" {
		req.URL.RawQuery = targetQuery + req.URL.RawQuery
	} else {
		req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
	}
}

(2)设置req.Host

tcpdumphosthttp
......P.H......P...(...POST /location?map_id=test HTTP/1.1
Host: 下游python服务域名
Content-Length: 3013
Traceid: 447e2cc680bed4f2fbfd3941bcda4a42
Traceparent: 00-447e2cc680bed4f2fbfd3941bcda4a42-fffc5c1b967b3f70-7462733d667273

4、为什么设置header里面的host没有生效?

gohttp
您可能感兴趣的文章: