refactor(internal): improve logging and byte format in proxy handlers

This commit is contained in:
wood chen 2024-10-31 08:07:03 +08:00
parent 8f2c035e93
commit b1b6a430cd
2 changed files with 69 additions and 12 deletions

View File

@ -128,13 +128,6 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
defer resp.Body.Close()
// 设置正确的 Content-Type
if strings.HasSuffix(strings.ToLower(decodedPath), ".mp4") {
w.Header().Set("Content-Type", "video/mp4")
} else if ct := resp.Header.Get("Content-Type"); ct != "" {
w.Header().Set("Content-Type", ct)
}
copyHeader(w.Header(), resp.Header)
// 设置响应状态码
@ -172,9 +165,9 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
// 记录访问日志
log.Printf("[%s] %s %s -> %s -> %d (%d bytes) [%v]",
log.Printf("[%s] %s %s -> %s -> %d (%s) [%v]",
getClientIP(r), r.Method, r.URL.Path, targetURL,
resp.StatusCode, bytesCopied, time.Since(startTime))
resp.StatusCode, formatBytes(bytesCopied), time.Since(startTime))
}
func copyHeader(dst, src http.Header) {
@ -197,3 +190,19 @@ func getClientIP(r *http.Request) string {
}
return r.RemoteAddr
}
func formatBytes(bytes int64) string {
const (
MB = 1024 * 1024
KB = 1024
)
switch {
case bytes >= MB:
return fmt.Sprintf("%.2f MB", float64(bytes)/MB)
case bytes >= KB:
return fmt.Sprintf("%.2f KB", float64(bytes)/KB)
default:
return fmt.Sprintf("%d Bytes", bytes)
}
}

View File

@ -1,12 +1,16 @@
package middleware
import (
"errors"
"fmt"
"io"
"log"
"net"
"net/http"
"proxy-go/internal/config"
"strings"
"syscall"
"time"
)
type FixedPathConfig struct {
@ -18,6 +22,7 @@ type FixedPathConfig struct {
func FixedPathProxyMiddleware(configs []config.FixedPathConfig) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
startTime := time.Now() // 添加时间记录
// 检查是否匹配任何固定路径
for _, cfg := range configs {
if strings.HasPrefix(r.URL.Path, cfg.Path) {
@ -28,6 +33,8 @@ func FixedPathProxyMiddleware(configs []config.FixedPathConfig) func(http.Handle
proxyReq, err := http.NewRequest(r.Method, targetURL, r.Body)
if err != nil {
http.Error(w, "Error creating proxy request", http.StatusInternalServerError)
log.Printf("[%s] %s %s -> 500 (error creating request: %v) [%v]",
getClientIP(r), r.Method, r.URL.Path, err, time.Since(startTime))
return
}
@ -49,6 +56,8 @@ func FixedPathProxyMiddleware(configs []config.FixedPathConfig) func(http.Handle
resp, err := client.Do(proxyReq)
if err != nil {
http.Error(w, "Error forwarding request", http.StatusBadGateway)
log.Printf("[%s] %s %s -> 502 (proxy error: %v) [%v]",
getClientIP(r), r.Method, r.URL.Path, err, time.Since(startTime))
return
}
defer resp.Body.Close()
@ -64,10 +73,16 @@ func FixedPathProxyMiddleware(configs []config.FixedPathConfig) func(http.Handle
w.WriteHeader(resp.StatusCode)
// 复制响应体
if _, err := io.Copy(w, resp.Body); err != nil {
// 已经发送了响应头,只能记录错误
log.Printf("Error copying response: %v", err)
bytesCopied, err := io.Copy(w, resp.Body)
if err := handleCopyError(err); err != nil {
log.Printf("[%s] Error copying response: %v", getClientIP(r), err)
}
// 记录成功的请求
log.Printf("[%s] %s %s -> %s -> %d (%s) [%v]",
getClientIP(r), r.Method, r.URL.Path, targetURL,
resp.StatusCode, formatBytes(bytesCopied), time.Since(startTime))
return
}
}
@ -91,3 +106,36 @@ func getClientIP(r *http.Request) string {
}
return r.RemoteAddr
}
func handleCopyError(err error) error {
if err == nil {
return nil
}
// 忽略常见的连接关闭错误
if errors.Is(err, syscall.EPIPE) || // broken pipe
errors.Is(err, syscall.ECONNRESET) || // connection reset by peer
strings.Contains(err.Error(), "broken pipe") ||
strings.Contains(err.Error(), "connection reset by peer") {
return nil
}
return err
}
// formatBytes 将字节数转换为可读的格式MB/KB/Bytes
func formatBytes(bytes int64) string {
const (
MB = 1024 * 1024
KB = 1024
)
switch {
case bytes >= MB:
return fmt.Sprintf("%.2f MB", float64(bytes)/MB)
case bytes >= KB:
return fmt.Sprintf("%.2f KB", float64(bytes)/KB)
default:
return fmt.Sprintf("%d Bytes", bytes)
}
}