fix(proxy): 修正代理请求 URI 和 Host 设置,添加调试日志
- 修复 ParseTargetURL 参数确保 HostClient.Addr 包含端口 - 设置请求 URI 为完整目标 URL(HostClient 要求格式一致) - 设置 Host header 为目标主机(连接需要 host:port 格式) - 添加 extractHostFromURL 辅助函数 - 添加 DEBUG 日志用于排查代理请求问题 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5b92e30b59
commit
aa73df964e
@ -199,7 +199,8 @@ func createBalancer(cfg *config.ProxyConfig) (loadbalance.Balancer, error) {
|
||||
// createHostClient 为后台目标 URL 创建 fasthttp.HostClient。
|
||||
func createHostClient(targetURL string, timeout config.ProxyTimeout, transportCfg *config.TransportConfig) *fasthttp.HostClient {
|
||||
// 从目标 URL 解析主机和协议
|
||||
addr, isTLS := netutil.ParseTargetURL(targetURL, false)
|
||||
// addDefaultPort=true 确保 HostClient.Addr 包含端口(host:port 格式)
|
||||
addr, isTLS := netutil.ParseTargetURL(targetURL, true)
|
||||
|
||||
// 默认值
|
||||
maxIdleConnDuration := 90 * time.Second
|
||||
@ -317,6 +318,10 @@ func FinalizeUpstreamVars(vc *variable.Context, upstreamAddr string, upstreamSta
|
||||
// 如果没有可用的健康目标,返回 502 Bad Gateway。
|
||||
// 如果后端请求失败,根据 next_upstream 配置尝试下一个目标。
|
||||
func (p *Proxy) ServeHTTP(ctx *fasthttp.RequestCtx) {
|
||||
// DEBUG: 打印请求信息
|
||||
logging.Debug().Msgf("[PROXY] 收到请求: path=%s, host=%s, method=%s",
|
||||
string(ctx.Path()), string(ctx.Host()), string(ctx.Method()))
|
||||
|
||||
// 上游变量捕获
|
||||
var upstreamAddr string
|
||||
var upstreamStatus int
|
||||
@ -374,9 +379,13 @@ func (p *Proxy) ServeHTTP(ctx *fasthttp.RequestCtx) {
|
||||
|
||||
attemptedTargets = append(attemptedTargets, target)
|
||||
|
||||
// DEBUG: 打印选中的目标
|
||||
logging.Debug().Msgf("[PROXY] 选中目标: url=%s, healthy=%v", target.URL, target.Healthy.Load())
|
||||
|
||||
// 获取所选目标的客户端
|
||||
client := p.getClient(target.URL)
|
||||
if client == nil {
|
||||
logging.Warn().Msgf("[PROXY] client 为 nil, url=%s", target.URL)
|
||||
// 标记为不健康并继续尝试下一个
|
||||
if p.healthChecker != nil {
|
||||
p.healthChecker.MarkUnhealthy(target)
|
||||
@ -384,6 +393,9 @@ func (p *Proxy) ServeHTTP(ctx *fasthttp.RequestCtx) {
|
||||
continue
|
||||
}
|
||||
|
||||
// DEBUG: 打印客户端信息
|
||||
logging.Debug().Msgf("[PROXY] client 信息: Addr=%s, IsTLS=%v", client.Addr, client.IsTLS)
|
||||
|
||||
// 增加连接计数(用于最少连接数负载均衡)
|
||||
loadbalance.IncrementConnections(target)
|
||||
|
||||
@ -413,6 +425,19 @@ func (p *Proxy) ServeHTTP(ctx *fasthttp.RequestCtx) {
|
||||
// 修改请求头
|
||||
p.modifyRequestHeaders(ctx, target)
|
||||
|
||||
// 关键:修改请求 URI 为完整的目标 URL
|
||||
// HostClient 要求 URI 格式必须与 Addr/IsTLS 一致
|
||||
// 例如:IsTLS=true 时,URI 应为 https://host/path
|
||||
targetURI := target.URL + string(ctx.URI().Path())
|
||||
if len(ctx.URI().QueryString()) > 0 {
|
||||
targetURI += "?" + string(ctx.URI().QueryString())
|
||||
}
|
||||
req.SetRequestURI(targetURI)
|
||||
|
||||
// DEBUG: 打印请求头
|
||||
logging.Debug().Msgf("[PROXY] 请求准备完成: Host=%s, URI=%s, targetURI=%s",
|
||||
string(req.Header.Host()), string(req.RequestURI()), targetURI)
|
||||
|
||||
// 尝试从缓存获取(如果启用)
|
||||
if p.cache != nil && attempt == 0 {
|
||||
hashKey, origKey := p.buildCacheKeyHash(ctx)
|
||||
@ -460,6 +485,13 @@ func (p *Proxy) ServeHTTP(ctx *fasthttp.RequestCtx) {
|
||||
err := client.Do(req, &ctx.Response)
|
||||
timing.MarkConnectEnd()
|
||||
|
||||
// DEBUG: 打印执行结果
|
||||
if err != nil {
|
||||
logging.Error().Msgf("[PROXY] 请求失败: url=%s, err=%v, errType=%T", target.URL, err, err)
|
||||
} else {
|
||||
logging.Debug().Msgf("[PROXY] 请求成功: url=%s, status=%d", target.URL, ctx.Response.StatusCode())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
loadbalance.DecrementConnections(target)
|
||||
|
||||
@ -734,9 +766,16 @@ func (p *Proxy) getClient(targetURL string) *fasthttp.HostClient {
|
||||
|
||||
// modifyRequestHeaders 在转发到后端之前修改请求头。
|
||||
// 添加标准代理请求头并应用自定义请求头配置。
|
||||
func (p *Proxy) modifyRequestHeaders(ctx *fasthttp.RequestCtx, _ *loadbalance.Target) {
|
||||
func (p *Proxy) modifyRequestHeaders(ctx *fasthttp.RequestCtx, target *loadbalance.Target) {
|
||||
headers := &ctx.Request.Header
|
||||
|
||||
// 设置 Host header 为目标主机
|
||||
// 从 target.URL 提取 host:port(HostClient 连接需要此格式)
|
||||
targetHost := extractHostFromURL(target.URL)
|
||||
if targetHost != "" {
|
||||
headers.Set("Host", targetHost)
|
||||
}
|
||||
|
||||
// 提取并设置 X-Forwarded 系列头
|
||||
fh := ExtractForwardedHeaders(ctx)
|
||||
SetForwardedHeaders(headers, fh, true)
|
||||
@ -900,3 +939,22 @@ func (p *Proxy) GetCacheStats() *cache.ProxyCacheStats {
|
||||
stats := p.cache.Stats()
|
||||
return &stats
|
||||
}
|
||||
|
||||
// extractHostFromURL 从 URL 中提取 host:port。
|
||||
// 用于设置代理请求的 Host header。
|
||||
func extractHostFromURL(urlStr string) string {
|
||||
// 移除协议前缀
|
||||
host := urlStr
|
||||
if strings.HasPrefix(host, "http://") {
|
||||
host = host[7:]
|
||||
} else if strings.HasPrefix(host, "https://") {
|
||||
host = host[8:]
|
||||
}
|
||||
|
||||
// 移除路径部分
|
||||
if idx := strings.Index(host, "/"); idx != -1 {
|
||||
host = host[:idx]
|
||||
}
|
||||
|
||||
return host
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user