修复脚本文件的字节大小不匹配问题
This commit is contained in:
@@ -168,17 +168,27 @@ func proxy(c *gin.Context, u string) {
|
|||||||
}
|
}
|
||||||
}(resp.Body)
|
}(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.")
|
c.String(http.StatusRequestEntityTooLarge, "File too large.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 清理安全相关的头
|
||||||
resp.Header.Del("Content-Security-Policy")
|
resp.Header.Del("Content-Security-Policy")
|
||||||
resp.Header.Del("Referrer-Policy")
|
resp.Header.Del("Referrer-Policy")
|
||||||
resp.Header.Del("Strict-Transport-Security")
|
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 key, values := range resp.Header {
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
c.Header(key, value)
|
c.Header(key, value)
|
||||||
@@ -196,10 +206,7 @@ func proxy(c *gin.Context, u string) {
|
|||||||
|
|
||||||
c.Status(resp.StatusCode)
|
c.Status(resp.StatusCode)
|
||||||
|
|
||||||
// 检查是否为.sh文件
|
// 处理响应体
|
||||||
isShellFile := strings.HasSuffix(strings.ToLower(u), ".sh")
|
|
||||||
isCompressed := resp.Header.Get("Content-Encoding") == "gzip"
|
|
||||||
|
|
||||||
if isShellFile {
|
if isShellFile {
|
||||||
// 获取真实域名
|
// 获取真实域名
|
||||||
realHost := c.Request.Header.Get("X-Forwarded-Host")
|
realHost := c.Request.Header.Get("X-Forwarded-Host")
|
||||||
@@ -211,7 +218,7 @@ func proxy(c *gin.Context, u string) {
|
|||||||
realHost = "https://" + realHost
|
realHost = "https://" + realHost
|
||||||
}
|
}
|
||||||
// 使用ProcessGitHubURLs处理.sh文件
|
// 使用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 {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("处理shell文件时发生错误: %v", err))
|
c.String(http.StatusInternalServerError, fmt.Sprintf("处理shell文件时发生错误: %v", err))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ func ProcessGitHubURLs(input io.ReadCloser, isCompressed bool, host string, isSh
|
|||||||
return input, 0, nil
|
return input, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 使用更大的缓冲区以提高性能
|
||||||
pipeReader, pipeWriter := io.Pipe()
|
pipeReader, pipeWriter := io.Pipe()
|
||||||
var written int64
|
var written int64
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ func ProcessGitHubURLs(input io.ReadCloser, isCompressed bool, host string, isSh
|
|||||||
|
|
||||||
defer input.Close()
|
defer input.Close()
|
||||||
|
|
||||||
reader := input
|
var reader io.Reader = input
|
||||||
if isCompressed {
|
if isCompressed {
|
||||||
debugPrintf("检测到压缩文件,进行解压处理\n")
|
debugPrintf("检测到压缩文件,进行解压处理\n")
|
||||||
gzipReader, gzipErr := gzip.NewReader(input)
|
gzipReader, gzipErr := gzip.NewReader(input)
|
||||||
@@ -80,52 +81,72 @@ func ProcessGitHubURLs(input io.ReadCloser, isCompressed bool, host string, isSh
|
|||||||
defer gzipReader.Close()
|
defer gzipReader.Close()
|
||||||
reader = gzipReader
|
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 {
|
if isCompressed {
|
||||||
gzipWriter := gzip.NewWriter(pipeWriter)
|
gzipWriter := gzip.NewWriter(writer)
|
||||||
defer gzipWriter.Close()
|
defer gzipWriter.Close()
|
||||||
bufWriter = bufio.NewWriterSize(gzipWriter, 4096)
|
writer = gzipWriter
|
||||||
} else {
|
|
||||||
bufWriter = bufio.NewWriterSize(pipeWriter, 4096)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bufWriter := bufio.NewWriterSize(writer, 32*1024) // 32KB buffer
|
||||||
defer bufWriter.Flush()
|
defer bufWriter.Flush()
|
||||||
|
|
||||||
written, err = processContent(bufReader, bufWriter, host)
|
written, err = processContent(bufReader, bufWriter, host)
|
||||||
|
if err != nil {
|
||||||
|
debugPrintf("处理内容时发生错误: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
debugPrintf("文件处理完成,共处理 %d 字节\n", written)
|
debugPrintf("文件处理完成,共处理 %d 字节\n", written)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return pipeReader, written, nil
|
return pipeReader, written, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// processContent 处理文件内容,返回处理的字节数
|
// processContent 优化处理文件内容的函数
|
||||||
func processContent(reader *bufio.Reader, writer *bufio.Writer, host string) (int64, error) {
|
func processContent(reader *bufio.Reader, writer *bufio.Writer, host string) (int64, error) {
|
||||||
var written int64
|
var written int64
|
||||||
lineNum := 0
|
lineNum := 0
|
||||||
|
|
||||||
|
// 预分配buffer以减少内存分配
|
||||||
|
buf := make([]byte, 32*1024)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
lineNum++
|
lineNum++
|
||||||
line, err := reader.ReadString('\n')
|
line, err := reader.ReadString('\n')
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
return written, err
|
return written, fmt.Errorf("读取行时发生错误: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if line != "" {
|
if line != "" {
|
||||||
// 在处理前先检查是否包含GitHub URL
|
// 在处理前先检查是否包含GitHub URL
|
||||||
matches := urlPattern.FindAllString(line, -1)
|
if strings.Contains(line, "github.com") ||
|
||||||
if len(matches) > 0 {
|
strings.Contains(line, "raw.githubusercontent.com") {
|
||||||
debugPrintf("\n在第 %d 行发现 %d 个GitHub URL:\n", lineNum, len(matches))
|
matches := urlPattern.FindAllString(line, -1)
|
||||||
for _, match := range matches {
|
if len(matches) > 0 {
|
||||||
debugPrintf("原始URL: %s\n", match)
|
debugPrintf("\n在第 %d 行发现 %d 个GitHub URL:\n", lineNum, len(matches))
|
||||||
|
for _, match := range matches {
|
||||||
|
debugPrintf("原始URL: %s\n", match)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
modifiedLine := processLine(line, host, lineNum)
|
modifiedLine := processLine(line, host, lineNum)
|
||||||
n, writeErr := writer.WriteString(modifiedLine)
|
n, writeErr := writer.WriteString(modifiedLine)
|
||||||
written += int64(n)
|
if writeErr != nil {
|
||||||
if writeErr != nil {
|
return written, fmt.Errorf("写入修改后的行时发生错误: %w", writeErr)
|
||||||
return written, 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
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保所有数据都被写入
|
||||||
|
if err := writer.Flush(); err != nil {
|
||||||
|
return written, fmt.Errorf("刷新缓冲区时发生错误: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return written, nil
|
return written, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user