diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b7cf74..7c70462 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # 更新日志 +25w22a - 2025-03-21 +--- +- PRE-RELEASE: 此版本是v3.0.1的预发布版本,请勿在生产环境中使用; +- FIX: 使用等效`c.Writer()`, 回归v2.5.0 func以修正问题 + 3.0.1 - 2025-03-21 --- - RELEASE: Next Step; 下一步; 完善v3的同时, 修正已知问题; v3会与v2.4.0及以上版本保证兼容关系, 可平顺升级; diff --git a/DEV-VERSION b/DEV-VERSION index 34cebe9..62cff45 100644 --- a/DEV-VERSION +++ b/DEV-VERSION @@ -1 +1 @@ -25w21e \ No newline at end of file +25w22a \ No newline at end of file diff --git a/go.mod b/go.mod index 8527184..f09866a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.1 require ( github.com/BurntSushi/toml v1.5.0 - github.com/WJQSERVER-STUDIO/go-utils/hwriter v0.0.3 + github.com/WJQSERVER-STUDIO/go-utils/copyb v0.0.4 github.com/WJQSERVER-STUDIO/go-utils/logger v1.5.0 github.com/cloudwego/hertz v0.9.6 github.com/hertz-contrib/http2 v0.1.8 @@ -15,7 +15,6 @@ require ( ) require ( - github.com/WJQSERVER-STUDIO/go-utils/copyb v0.0.4 // indirect github.com/WJQSERVER-STUDIO/go-utils/log v0.0.1 // indirect github.com/bytedance/gopkg v0.1.1 // indirect github.com/bytedance/sonic v1.13.1 // indirect diff --git a/go.sum b/go.sum index 5174ab3..49be6ae 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,6 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/WJQSERVER-STUDIO/go-utils/copyb v0.0.4 h1:JLtFd00AdFg/TP+dtvIzLkdHwKUGPOAijN1sMtEYoFg= github.com/WJQSERVER-STUDIO/go-utils/copyb v0.0.4/go.mod h1:FZ6XE+4TKy4MOfX1xWKe6Rwsg0ucYFCdNh1KLvyKTfc= -github.com/WJQSERVER-STUDIO/go-utils/hwriter v0.0.3 h1:4kZH8GauRDR2R3ywgyob2Clyh3o1o/DPZCxknzi9HUU= -github.com/WJQSERVER-STUDIO/go-utils/hwriter v0.0.3/go.mod h1:U3dVP2MzKJfK6dPiobxmSdynibqCOn1mxQEVLylESWA= github.com/WJQSERVER-STUDIO/go-utils/log v0.0.1 h1:gJEQspQPB527Vp2FPcdOrynQEj3YYtrg1ixVSB/JvZM= github.com/WJQSERVER-STUDIO/go-utils/log v0.0.1/go.mod h1:j9Q+xnwpOfve7/uJnZ2izRQw6NNoXjvJHz7vUQAaLZE= github.com/WJQSERVER-STUDIO/go-utils/logger v1.5.0 h1:Uk4N7Sh4OPth3am3xVv17JlAm7tsna97ZLQRpQj7r5c= diff --git a/proxy/chunkreq.go b/proxy/chunkreq.go index 819d5c0..fb78762 100644 --- a/proxy/chunkreq.go +++ b/proxy/chunkreq.go @@ -9,7 +9,7 @@ import ( "net/http" "strconv" - "github.com/WJQSERVER-STUDIO/go-utils/hwriter" + "github.com/WJQSERVER-STUDIO/go-utils/copyb" "github.com/cloudwego/hertz/pkg/app" hresp "github.com/cloudwego/hertz/pkg/protocol/http1/resp" ) @@ -130,7 +130,8 @@ func ChunkedProxyRequest(ctx context.Context, c *app.RequestContext, u string, c logInfo("Is Shell: %s %s %s %s %s", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Header.GetProtocol()) c.Header("Content-Length", "") - err := ProcessLinksAndWriteChunked(resp.Body, compress, string(c.Request.Host()), cfg, c) + //err := ProcessLinksAndWriteChunked(resp.Body, compress, string(c.Request.Host()), cfg, c) + _, err := processLinks(resp.Body, c.Response.BodyWriter(), compress, string(c.Request.Host()), cfg) if err != nil { logError("%s %s %s %s %s Failed to copy response body: %v", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Header.GetProtocol(), err) @@ -139,7 +140,9 @@ func ChunkedProxyRequest(ctx context.Context, c *app.RequestContext, u string, c c.Flush() // 确保刷入 } } else { - err = hwriter.Writer(resp.Body, c) + //err = hwriter.Writer(resp.Body, c) + //writer := c.Response.BodyWriter() + _, err := copyb.Copy(c.Response.BodyWriter(), resp.Body) if err != nil { logError("%s %s %s %s %s Failed to copy response body: %v", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Header.GetProtocol(), err) return diff --git a/proxy/gitreq.go b/proxy/gitreq.go index f1330de..0405a0f 100644 --- a/proxy/gitreq.go +++ b/proxy/gitreq.go @@ -9,7 +9,7 @@ import ( "net/http" "strconv" - "github.com/WJQSERVER-STUDIO/go-utils/hwriter" + "github.com/WJQSERVER-STUDIO/go-utils/copyb" "github.com/cloudwego/hertz/pkg/app" ) @@ -118,7 +118,8 @@ func GitReq(ctx context.Context, c *app.RequestContext, u string, cfg *config.Co } c.Status(resp.StatusCode) - err = hwriter.Writer(resp.Body, c) + //err = hwriter.Writer(resp.Body, c) + _, err = copyb.Copy(c.Response.BodyWriter(), resp.Body) if err != nil { logError("%s %s %s %s %s Failed to copy response body: %v", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Header.GetProtocol(), err) diff --git a/proxy/match.go b/proxy/match.go index 7a6e818..5f1f40f 100644 --- a/proxy/match.go +++ b/proxy/match.go @@ -373,3 +373,83 @@ func extractParts(rawURL string) (string, string, string, url.Values, error) { return repoOwner, repoName, remainingPath, queryParams, nil } + +// processLinks 处理链接并将结果写入输出流 +func processLinks(input io.Reader, output io.Writer, compress string, host string, cfg *config.Config) (written int64, err error) { + var reader *bufio.Reader + + if compress == "gzip" { + // 解压gzip + gzipReader, err := gzip.NewReader(input) + if err != nil { + return 0, fmt.Errorf("gzip解压错误: %v", err) + } + defer gzipReader.Close() + reader = bufio.NewReader(gzipReader) + } else { + reader = bufio.NewReader(input) + } + + var writer *bufio.Writer + var gzipWriter *gzip.Writer + + // 根据是否gzip确定 writer 的创建 + if compress == "gzip" { + gzipWriter = gzip.NewWriter(output) + writer = bufio.NewWriterSize(gzipWriter, 4096) //设置缓冲区大小 + } else { + writer = bufio.NewWriterSize(output, 4096) + } + + //确保writer关闭 + defer func() { + var closeErr error // 局部变量,用于保存defer中可能发生的错误 + + if gzipWriter != nil { + if closeErr = gzipWriter.Close(); closeErr != nil { + logError("gzipWriter close failed %v", closeErr) + // 如果已经存在错误,则保留。否则,记录此错误。 + if err == nil { + err = closeErr + } + } + } + if flushErr := writer.Flush(); flushErr != nil { + logError("writer flush failed %v", flushErr) + // 如果已经存在错误,则保留。否则,记录此错误。 + if err == nil { + err = flushErr + } + } + }() + + // 使用正则表达式匹配 http 和 https 链接 + urlPattern := regexp.MustCompile(`https?://[^\s'"]+`) + for { + line, err := reader.ReadString('\n') + if err != nil { + if err == io.EOF { + break // 文件结束 + } + return written, fmt.Errorf("读取行错误: %v", err) // 传递错误 + } + + // 替换所有匹配的 URL + modifiedLine := urlPattern.ReplaceAllStringFunc(line, func(originalURL string) string { + return modifyURL(originalURL, host, cfg) + }) + + n, werr := writer.WriteString(modifiedLine) + written += int64(n) // 更新写入的字节数 + if werr != nil { + return written, fmt.Errorf("写入文件错误: %v", werr) // 传递错误 + } + } + + // 在返回之前,再刷新一次 + if fErr := writer.Flush(); fErr != nil { + return written, fErr + } + + return written, nil +}