From 35361c36a6545727910e87abd59d1575ccf0ab40 Mon Sep 17 00:00:00 2001 From: NewName Date: Sun, 18 May 2025 09:46:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=84=9A=E6=9C=AC=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=9A=84=E5=AD=97=E8=8A=82=E5=A4=A7=E5=B0=8F=E4=B8=8D?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ghproxy/main.go | 21 +++++++++----- ghproxy/proxysh.go | 69 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 62 insertions(+), 28 deletions(-) diff --git a/ghproxy/main.go b/ghproxy/main.go index 044ed9e..effcb7e 100644 --- a/ghproxy/main.go +++ b/ghproxy/main.go @@ -168,17 +168,27 @@ func proxy(c *gin.Context, u string) { } }(resp.Body) - if contentLength, ok := resp.Header["Content-Length"]; ok { - if size, err := strconv.Atoi(contentLength[0]); err == nil && size > sizeLimit { + // 检查文件大小限制 + if contentLength := resp.Header.Get("Content-Length"); contentLength != "" { + if size, err := strconv.Atoi(contentLength); err == nil && size > sizeLimit { c.String(http.StatusRequestEntityTooLarge, "File too large.") return } } + // 清理安全相关的头 resp.Header.Del("Content-Security-Policy") resp.Header.Del("Referrer-Policy") resp.Header.Del("Strict-Transport-Security") + + // 对于需要处理的shell文件,我们使用chunked传输 + isShellFile := strings.HasSuffix(strings.ToLower(u), ".sh") + if isShellFile { + resp.Header.Del("Content-Length") + resp.Header.Set("Transfer-Encoding", "chunked") + } + // 复制其他响应头 for key, values := range resp.Header { for _, value := range values { c.Header(key, value) @@ -196,10 +206,7 @@ func proxy(c *gin.Context, u string) { c.Status(resp.StatusCode) - // 检查是否为.sh文件 - isShellFile := strings.HasSuffix(strings.ToLower(u), ".sh") - isCompressed := resp.Header.Get("Content-Encoding") == "gzip" - + // 处理响应体 if isShellFile { // 获取真实域名 realHost := c.Request.Header.Get("X-Forwarded-Host") @@ -211,7 +218,7 @@ func proxy(c *gin.Context, u string) { realHost = "https://" + realHost } // 使用ProcessGitHubURLs处理.sh文件 - processedBody, _, err := ProcessGitHubURLs(resp.Body, isCompressed, realHost, true) + processedBody, _, err := ProcessGitHubURLs(resp.Body, resp.Header.Get("Content-Encoding") == "gzip", realHost, true) if err != nil { c.String(http.StatusInternalServerError, fmt.Sprintf("处理shell文件时发生错误: %v", err)) return diff --git a/ghproxy/proxysh.go b/ghproxy/proxysh.go index 83df8cf..ba71bcd 100644 --- a/ghproxy/proxysh.go +++ b/ghproxy/proxysh.go @@ -53,6 +53,7 @@ func ProcessGitHubURLs(input io.ReadCloser, isCompressed bool, host string, isSh return input, 0, nil } + // 使用更大的缓冲区以提高性能 pipeReader, pipeWriter := io.Pipe() var written int64 @@ -69,7 +70,7 @@ func ProcessGitHubURLs(input io.ReadCloser, isCompressed bool, host string, isSh defer input.Close() - reader := input + var reader io.Reader = input if isCompressed { debugPrintf("检测到压缩文件,进行解压处理\n") gzipReader, gzipErr := gzip.NewReader(input) @@ -80,52 +81,72 @@ func ProcessGitHubURLs(input io.ReadCloser, isCompressed bool, host string, isSh defer gzipReader.Close() reader = gzipReader } - bufReader := bufio.NewReader(reader) - var bufWriter *bufio.Writer + // 使用更大的缓冲区 + bufReader := bufio.NewReaderSize(reader, 32*1024) // 32KB buffer + var writer io.Writer = pipeWriter + if isCompressed { - gzipWriter := gzip.NewWriter(pipeWriter) + gzipWriter := gzip.NewWriter(writer) defer gzipWriter.Close() - bufWriter = bufio.NewWriterSize(gzipWriter, 4096) - } else { - bufWriter = bufio.NewWriterSize(pipeWriter, 4096) + writer = gzipWriter } + + bufWriter := bufio.NewWriterSize(writer, 32*1024) // 32KB buffer defer bufWriter.Flush() written, err = processContent(bufReader, bufWriter, host) + if err != nil { + debugPrintf("处理内容时发生错误: %v\n", err) + return + } + debugPrintf("文件处理完成,共处理 %d 字节\n", written) }() return pipeReader, written, nil } -// processContent 处理文件内容,返回处理的字节数 +// processContent 优化处理文件内容的函数 func processContent(reader *bufio.Reader, writer *bufio.Writer, host string) (int64, error) { var written int64 lineNum := 0 + // 预分配buffer以减少内存分配 + buf := make([]byte, 32*1024) + for { lineNum++ line, err := reader.ReadString('\n') if err != nil && err != io.EOF { - return written, err + return written, fmt.Errorf("读取行时发生错误: %w", err) } if line != "" { // 在处理前先检查是否包含GitHub URL - matches := urlPattern.FindAllString(line, -1) - if len(matches) > 0 { - debugPrintf("\n在第 %d 行发现 %d 个GitHub URL:\n", lineNum, len(matches)) - for _, match := range matches { - debugPrintf("原始URL: %s\n", match) + if strings.Contains(line, "github.com") || + strings.Contains(line, "raw.githubusercontent.com") { + matches := urlPattern.FindAllString(line, -1) + if len(matches) > 0 { + debugPrintf("\n在第 %d 行发现 %d 个GitHub URL:\n", lineNum, len(matches)) + for _, match := range matches { + debugPrintf("原始URL: %s\n", match) + } } - } - - modifiedLine := processLine(line, host, lineNum) - n, writeErr := writer.WriteString(modifiedLine) - written += int64(n) - if writeErr != nil { - return written, writeErr + + modifiedLine := processLine(line, host, lineNum) + n, writeErr := writer.WriteString(modifiedLine) + if writeErr != nil { + return written, fmt.Errorf("写入修改后的行时发生错误: %w", writeErr) + } + written += int64(n) + } else { + // 如果行中没有GitHub URL,直接写入 + n, writeErr := writer.WriteString(line) + if writeErr != nil { + return written, fmt.Errorf("写入原始行时发生错误: %w", writeErr) + } + written += int64(n) } } @@ -133,6 +154,12 @@ func processContent(reader *bufio.Reader, writer *bufio.Writer, host string) (in break } } + + // 确保所有数据都被写入 + if err := writer.Flush(); err != nil { + return written, fmt.Errorf("刷新缓冲区时发生错误: %w", err) + } + return written, nil }