From 969322a912c215ac713389e1f5a859cebd3bca1e Mon Sep 17 00:00:00 2001 From: black1552 Date: Fri, 6 Mar 2026 10:52:26 +0800 Subject: [PATCH] =?UTF-8?q?refactor(server):=20=E9=87=8D=E6=9E=84=E7=BD=91?= =?UTF-8?q?=E5=85=B3=E8=AF=B7=E6=B1=82=E4=BB=A3=E7=90=86=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用标准库 httputil.NewSingleHostReverseProxy 替代自定义 HTTP 客户端 - 移除 gclient、gcache 和相关依赖包导入 - 添加自定义 Director 函数处理目标 URL 设置 - 实现错误处理机制和 Bad Gateway 响应 - 简化 WebSocket 连接支持逻辑 - 优化请求头和响应头处理流程 --- server/gateway.go | 73 ++++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 52 deletions(-) diff --git a/server/gateway.go b/server/gateway.go index 39ea1d4..5ce4187 100644 --- a/server/gateway.go +++ b/server/gateway.go @@ -1,62 +1,19 @@ package server import ( - "fmt" - "io" "net/http" "net/http/httputil" "net/url" - "time" "git.magicany.cc/black1552/gf-common/log" - "github.com/gogf/gf/v2/net/gclient" "github.com/gogf/gf/v2/net/ghttp" - "github.com/gogf/gf/v2/os/gcache" "github.com/gogf/gf/v2/os/gctx" ) +// BuildRequest 反向代理请求到指定主机 +// 自动支持所有 HTTP 方法及 WebSocket 连接 func BuildRequest(r *ghttp.Request, host string) { - client := gclient.New() - // 构建目标URL而不是直接复制RequestURI - targetURL := host + r.URL.Path - if r.URL.RawQuery != "" { - targetURL += "?" + r.URL.RawQuery - } - // 复制请求头 - for key, values := range r.Header { - for _, value := range values { - client.SetHeader(key, value) - } - } - response, err := client.DoRequest(gctx.New(), r.Method, targetURL, r.GetBody()) - if err != nil { - log.Error(gctx.New(), "request error:", err) - panic(fmt.Sprintf("request error: %v", err)) - } - defer response.Body.Close() - // 读取响应体 - respBody, err := io.ReadAll(response.Body) - if err != nil { - log.Error(gctx.New(), "read response body error:", err) - panic(fmt.Sprintf("read response body error: %v", err)) - } - - // 复制响应头 - for key, values := range response.Header { - for _, value := range values { - r.Response.Header().Add(key, value) - } - } - gcache.Set(gctx.New(), "host", host, 1*time.Second) - // 设置响应状态码并写入响应体 - r.Response.Status = response.StatusCode - r.Response.Write(respBody) -} - -// ProxyWebSocket 处理 WebSocket 连接的代理 -func ProxyWebSocket(r *ghttp.Request, targetHost string) { - // 解析目标主机 URL - targetURL, err := url.Parse(targetHost) + targetURL, err := url.Parse(host) if err != nil { log.Error(gctx.New(), "parse target host error:", err) r.Response.WriteStatus(http.StatusInternalServerError) @@ -64,13 +21,25 @@ func ProxyWebSocket(r *ghttp.Request, targetHost string) { return } - // 创建反向代理 proxy := httputil.NewSingleHostReverseProxy(targetURL) - // 修改请求 URL,保留原始路径和查询参数 - r.URL.Scheme = targetURL.Scheme - r.URL.Host = targetURL.Host - log.Info(gctx.New(), r.GetBodyString()) - // 处理 WebSocket 连接 + // 自定义 Director 来设置目标 URL,保留原始请求的所有参数 + proxy.Director = func(req *http.Request) { + req.URL.Scheme = targetURL.Scheme + req.URL.Host = targetURL.Host + req.URL.Path = r.URL.Path + req.URL.RawQuery = r.URL.RawQuery + // 保留原始 Host 头 + req.Host = r.Host + } + + // 错误处理 + proxy.ErrorHandler = func(w http.ResponseWriter, req *http.Request, err error) { + log.Error(gctx.New(), "proxy error:", err) + w.WriteHeader(http.StatusBadGateway) + w.Write([]byte("Bad Gateway")) + } + + // ServeHTTP 会自动处理 WebSocket 升级和所有 HTTP 方法 proxy.ServeHTTP(r.Response.Writer, r.Request) }