diff --git a/CHANGELOG.md b/CHANGELOG.md index 56c983f..20df616 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # 更新日志 +25w12a +--- +- PRE-RELEASE: 此版本是v2.0.8/v2.1.0的预发布版本,请勿在生产环境中使用; +- CHANGE: 更新looger版本至v1.3.0 +- CHANGE: 改进日志相关 +- ADD: 加入日志等级配置项 + 2.0.7 --- - RELEASE: v2.0.7正式版发布; diff --git a/DEV-VERSION b/DEV-VERSION index 9548754..e56b4bf 100644 --- a/DEV-VERSION +++ b/DEV-VERSION @@ -1 +1 @@ -25w11a +25w12a \ No newline at end of file diff --git a/README.md b/README.md index 131a8e4..229da37 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ staticPath = "/data/www" # 静态页面文件路径 [log] logFilePath = "/data/ghproxy/log/ghproxy.log" # 日志文件路径 maxLogSize = 5 # MB 日志文件最大大小 +level = "info" # 日志级别 dump, debug, info, warn, error, none [cors] enabled = true # 是否开启跨域 diff --git a/api/api.go b/api/api.go index 2216787..9aae5f6 100644 --- a/api/api.go +++ b/api/api.go @@ -15,6 +15,8 @@ var ( var ( logw = logger.Logw + LogDump = logger.LogDump + logDebug = logger.LogDebug logInfo = logger.LogInfo logWarning = logger.LogWarning logError = logger.LogError diff --git a/auth/auth-header.go b/auth/auth-header.go index 5089254..4cdff18 100644 --- a/auth/auth-header.go +++ b/auth/auth-header.go @@ -13,7 +13,7 @@ func AuthHeaderHandler(c *gin.Context, cfg *config.Config) (isValid bool, err st } // 获取"GH-Auth"的值 authToken := c.GetHeader("GH-Auth") - logInfo("%s %s %s %s %s AUTH_TOKEN: %s", c.Request.Method, c.Request.Host, c.Request.URL.Path, c.Request.Proto, c.Request.RemoteAddr, authToken) + logDebug("%s %s %s %s %s AUTH_TOKEN: %s", c.Request.Method, c.Request.Host, c.Request.URL.Path, c.Request.Proto, c.Request.RemoteAddr, authToken) if authToken == "" { err := "Auth Header == nil" return false, err @@ -25,6 +25,5 @@ func AuthHeaderHandler(c *gin.Context, cfg *config.Config) (isValid bool, err st return false, err } - logInfo("auth SUCCESS: %t", isValid) return isValid, "" } diff --git a/auth/auth-parameters.go b/auth/auth-parameters.go index c14e23a..20d1ac2 100644 --- a/auth/auth-parameters.go +++ b/auth/auth-parameters.go @@ -13,7 +13,7 @@ func AuthParametersHandler(c *gin.Context, cfg *config.Config) (isValid bool, er } authToken := c.Query("auth_token") - logInfo("%s %s %s %s %s AUTH_TOKEN: %s", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Request.UserAgent(), c.Request.Proto, authToken) + logDebug("%s %s %s %s %s AUTH_TOKEN: %s", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Request.UserAgent(), c.Request.Proto, authToken) if authToken == "" { err := "Auth token == nil" @@ -26,6 +26,5 @@ func AuthParametersHandler(c *gin.Context, cfg *config.Config) (isValid bool, er return false, err } - logInfo("auth SUCCESS: %t", isValid) return isValid, "" } diff --git a/auth/auth.go b/auth/auth.go index 643661a..0705b8d 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -9,6 +9,8 @@ import ( var ( logw = logger.Logw + LogDump = logger.LogDump + logDebug = logger.LogDebug logInfo = logger.LogInfo logWarning = logger.LogWarning logError = logger.LogError @@ -21,7 +23,7 @@ func Init(cfg *config.Config) { if cfg.Whitelist.Enabled { LoadWhitelist(cfg) } - logInfo("Auth Init") + logDebug("Auth Init") } func AuthHandler(c *gin.Context, cfg *config.Config) (isValid bool, err string) { @@ -32,10 +34,10 @@ func AuthHandler(c *gin.Context, cfg *config.Config) (isValid bool, err string) isValid, err = AuthHeaderHandler(c, cfg) return isValid, err } else if cfg.Auth.AuthMethod == "" { - logWarning("Auth method not set") + logError("Auth method not set") return true, "" } else { - logWarning("Auth method not supported") + logError("Auth method not supported") return false, "Auth method not supported" } } diff --git a/config/config.go b/config/config.go index ea325a4..de72a4b 100644 --- a/config/config.go +++ b/config/config.go @@ -31,6 +31,7 @@ type PagesConfig struct { type LogConfig struct { LogFilePath string `toml:"logFilePath"` MaxLogSize int `toml:"maxLogSize"` + Level string `toml:"level"` } type CORSConfig struct { diff --git a/config/config.toml b/config/config.toml index 5d1900f..d981545 100644 --- a/config/config.toml +++ b/config/config.toml @@ -12,6 +12,7 @@ staticDir = "/data/www" [log] logFilePath = "/data/ghproxy/log/ghproxy.log" maxLogSize = 5 # MB +level = "info" # dump, debug, info, warn, error, none [cors] enabled = true diff --git a/deploy/config.toml b/deploy/config.toml index 6053f12..ec684ec 100644 --- a/deploy/config.toml +++ b/deploy/config.toml @@ -8,6 +8,7 @@ debug = false [pages] enabled = false staticDir = "/usr/local/ghproxy/pages" +level = "info" [log] logFilePath = "/usr/local/ghproxy/log/ghproxy.log" diff --git a/go.mod b/go.mod index cdd0660..64fa66c 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.6 require ( github.com/BurntSushi/toml v1.4.0 - github.com/WJQSERVER-STUDIO/go-utils/logger v1.2.0 + github.com/WJQSERVER-STUDIO/go-utils/logger v1.3.0 github.com/gin-gonic/gin v1.10.0 golang.org/x/time v0.10.0 ) @@ -34,6 +34,6 @@ require ( golang.org/x/net v0.34.0 // indirect golang.org/x/sys v0.30.0 // indirect golang.org/x/text v0.22.0 // indirect - google.golang.org/protobuf v1.36.4 // indirect + google.golang.org/protobuf v1.36.5 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 1f28606..2fe95a6 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/WJQSERVER-STUDIO/go-utils/logger v1.2.0 h1:6JkiVGRasfdBxEV8Qnv5x00Bq4qX1Tg6f58Ar/D2YX0= -github.com/WJQSERVER-STUDIO/go-utils/logger v1.2.0/go.mod h1:oW884JCCPDU6c906LI0uKXndWLiRvjb9LkGYC2cqRO8= +github.com/WJQSERVER-STUDIO/go-utils/logger v1.3.0 h1:rOvutC4zYfvtSGN2CNZrycjtq8dLpfu7ypy7tTEErPY= +github.com/WJQSERVER-STUDIO/go-utils/logger v1.3.0/go.mod h1:oW884JCCPDU6c906LI0uKXndWLiRvjb9LkGYC2cqRO8= github.com/bytedance/sonic v1.12.8 h1:4xYRVRlXIgvSZ4e8iVTlMF5szgpXd4AfvuWgA8I8lgs= github.com/bytedance/sonic v1.12.8/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= @@ -80,8 +80,8 @@ golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 36be801..e5fd3c1 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "io/fs" - "log" "net/http" "time" @@ -40,6 +39,8 @@ var ( var ( logw = logger.Logw + LogDump = logger.LogDump + logDebug = logger.LogDebug logInfo = logger.LogInfo logWarning = logger.LogWarning logError = logger.LogError @@ -53,20 +54,24 @@ func loadConfig() { var err error cfg, err = config.LoadConfig(cfgfile) if err != nil { - log.Fatalf("Failed to load config: %v", err) + fmt.Printf("Failed to load config: %v\n", err) + } + if cfg.Server.Debug { + fmt.Println("Config File Path: ", cfgfile) + fmt.Printf("Loaded config: %v\n", cfg) } - fmt.Println("Config File Path: ", cfgfile) - fmt.Printf("Loaded config: %v\n", cfg) } func setupLogger(cfg *config.Config) { var err error err = logger.Init(cfg.Log.LogFilePath, cfg.Log.MaxLogSize) if err != nil { - log.Fatalf("Failed to initialize logger: %v", err) + fmt.Printf("Failed to initialize logger: %v\n", err) } - logInfo("Config File Path: ", cfgfile) - logInfo("Loaded config: %v\n", cfg) + logger.SetLogLevel(cfg.Log.Level) + fmt.Printf("Log Level: %s\n", cfg.Log.Level) + logDebug("Config File Path: ", cfgfile) + logDebug("Loaded config: %v\n", cfg) logInfo("Init Completed") } @@ -87,7 +92,6 @@ func setupRateLimit(cfg *config.Config) { } else { logError("Invalid RateLimit Method: %s", cfg.RateLimit.RateMethod) } - logInfo("Rate Limit Loaded") } } @@ -116,6 +120,8 @@ func init() { runMode = "release" } + logDebug("Run Mode: %s", runMode) + gin.LoggerWithWriter(io.Discard) router = gin.New() router.Use(gin.Recovery()) @@ -141,7 +147,7 @@ func init() { } else if !cfg.Pages.Enabled { pages, err := fs.Sub(pagesFS, "pages") if err != nil { - log.Fatalf("Failed when processing pages: %s", err) + logError("Failed when processing pages: %s", err) } router.GET("/", gin.WrapH(http.FileServer(http.FS(pages)))) router.GET("/favicon.ico", gin.WrapH(http.FileServer(http.FS(pages)))) @@ -152,6 +158,8 @@ func init() { }) fmt.Printf("GHProxy Version: %s\n", version) + fmt.Printf("A Go Based High-Performance Github Proxy \n") + fmt.Printf("Made by WJQSERVER-STUDIO\n") } func main() { diff --git a/proxy/authpass.go b/proxy/authpass.go index b5eba12..c6d77a2 100644 --- a/proxy/authpass.go +++ b/proxy/authpass.go @@ -11,6 +11,7 @@ func AuthPassThrough(c *gin.Context, cfg *config.Config, req *http.Request) { if cfg.Auth.PassThrough { token := c.Query("token") if token != "" { + logDebug("%s %s %s %s %s Auth-PassThrough: token %s", c.ClientIP(), c.Request.Method, c.Request.URL.String(), c.Request.Header.Get("User-Agent"), c.Request.Proto, token) switch cfg.Auth.AuthMethod { case "parameters": if !cfg.Auth.Enabled { diff --git a/proxy/chunkreq.go b/proxy/chunkreq.go index 44b5759..181151a 100644 --- a/proxy/chunkreq.go +++ b/proxy/chunkreq.go @@ -54,12 +54,12 @@ func initChunkedHTTPClient() { func ChunkedProxyRequest(c *gin.Context, u string, cfg *config.Config, mode string, runMode string) { method := c.Request.Method - logInfo("%s %s %s %s %s", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto) + logInfo("%s %s %s %s %s Chunked-Proxy-Request", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto) // 发送HEAD请求, 预获取Content-Length headReq, err := http.NewRequest("HEAD", u, nil) if err != nil { - HandleError(c, fmt.Sprintf("创建HEAD请求失败: %v", err)) + HandleError(c, fmt.Sprintf("Failed to create request: %v", err)) return } setRequestHeaders(c, headReq) @@ -108,7 +108,7 @@ func ChunkedProxyRequest(c *gin.Context, u string, cfg *config.Config, mode stri // 创建请求 req, err := http.NewRequest(method, u, bodyReader) if err != nil { - HandleError(c, fmt.Sprintf("创建请求失败: %v", err)) + HandleError(c, fmt.Sprintf("Failed to create request: %v", err)) return } @@ -118,7 +118,7 @@ func ChunkedProxyRequest(c *gin.Context, u string, cfg *config.Config, mode stri resp, err := cclient.Do(req) if err != nil { - HandleError(c, fmt.Sprintf("发送请求失败: %v", err)) + HandleError(c, fmt.Sprintf("Failed to send request: %v", err)) return } defer resp.Body.Close() @@ -171,7 +171,7 @@ func ChunkedProxyRequest(c *gin.Context, u string, cfg *config.Config, mode stri _, err = io.CopyBuffer(c.Writer, resp.Body, buffer) if err != nil { - logError("%s %s %s %s %s 响应复制错误: %v", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto, err) + logError("%s %s %s %s %s Failed to copy response body: %v", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto, err) return } else { c.Writer.Flush() // 确保刷入 diff --git a/proxy/gitreq.go b/proxy/gitreq.go index 6dbd20d..568a1ac 100644 --- a/proxy/gitreq.go +++ b/proxy/gitreq.go @@ -38,7 +38,7 @@ func GitReq(c *gin.Context, u string, cfg *config.Config, mode string, runMode s // 发送HEAD请求, 预获取Content-Length headReq, err := http.NewRequest("HEAD", u, nil) if err != nil { - HandleError(c, fmt.Sprintf("创建HEAD请求失败: %v", err)) + HandleError(c, fmt.Sprintf("Failed to create request: %v", err)) return } setRequestHeaders(c, headReq) @@ -80,7 +80,7 @@ func GitReq(c *gin.Context, u string, cfg *config.Config, mode string, runMode s // 创建请求 req, err := http.NewRequest(method, u, bodyReader) if err != nil { - HandleError(c, fmt.Sprintf("创建请求失败: %v", err)) + HandleError(c, fmt.Sprintf("Failed to create request: %v", err)) return } setRequestHeaders(c, req) diff --git a/proxy/handler.go b/proxy/handler.go index 81d5690..b0ad7d1 100644 --- a/proxy/handler.go +++ b/proxy/handler.go @@ -54,6 +54,8 @@ func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *ra username, repo := MatchUserRepo(rawPath, cfg, c, matches) // 匹配用户名和仓库名 logInfo("%s %s %s %s %s Matched-Username: %s, Matched-Repo: %s", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, username, repo) + // dump log 记录详细信息 c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, full Header + LogDump("%s %s %s %s %s %s", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, c.Request.Header) repouser := fmt.Sprintf("%s/%s", username, repo) // 白名单检查 @@ -83,7 +85,7 @@ func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *ra matches = CheckURL(rawPath, c) if matches == nil { c.AbortWithStatus(http.StatusNotFound) - logError("%s %s %s %s %s 404-NOMATCH", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto) + logWarning("%s %s %s %s %s 404-NOMATCH", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto) return } @@ -91,7 +93,7 @@ func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *ra if exps[5].MatchString(rawPath) { if cfg.Auth.AuthMethod != "header" || !cfg.Auth.Enabled { c.JSON(http.StatusForbidden, gin.H{"error": "HeaderAuth is not enabled."}) - logWarning("%s %s %s %s %s HeaderAuth-Error: HeaderAuth is not enabled.", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto) + logError("%s %s %s %s %s HeaderAuth-Error: HeaderAuth is not enabled.", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto) return } } @@ -110,7 +112,7 @@ func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *ra } // IP METHOD URL USERAGENT PROTO MATCHES - logInfo("%s %s %s %s %s Matches: %v", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, matches) + logDebug("%s %s %s %s %s Matches: %v", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, matches) switch { case exps[0].MatchString(rawPath), exps[1].MatchString(rawPath), exps[3].MatchString(rawPath), exps[4].MatchString(rawPath): diff --git a/proxy/matchrepo.go b/proxy/matchrepo.go index 5a5d000..a074193 100644 --- a/proxy/matchrepo.go +++ b/proxy/matchrepo.go @@ -18,7 +18,7 @@ var ( // 提取用户名和仓库名 func MatchUserRepo(rawPath string, cfg *config.Config, c *gin.Context, matches []string) (string, string) { if gistMatches := gistRegex.FindStringSubmatch(rawPath); len(gistMatches) == 3 { - logInfo("%s %s %s %s %s Matched-Username: %s", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, gistMatches[1]) + LogDump("%s %s %s %s %s Matched-Username: %s", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, gistMatches[1]) return gistMatches[1], "" } // 定义路径 diff --git a/proxy/proxy.go b/proxy/proxy.go index ca45203..3b9d3ff 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -13,6 +13,8 @@ import ( // 日志模块 var ( logw = logger.Logw + LogDump = logger.LogDump + logDebug = logger.LogDebug logInfo = logger.LogInfo logWarning = logger.LogWarning logError = logger.LogError @@ -31,6 +33,7 @@ var exps = []*regexp.Regexp{ func readRequestBody(c *gin.Context) ([]byte, error) { body, err := io.ReadAll(c.Request.Body) if err != nil { + logError("failed to read request body: %v", err) return nil, fmt.Errorf("failed to read request body: %v", err) } defer c.Request.Body.Close() @@ -59,7 +62,7 @@ func SendRequest(c *gin.Context, req *req.Request, method, url string) (*req.Res func HandleError(c *gin.Context, message string) { c.String(http.StatusInternalServerError, fmt.Sprintf("server error %v", message)) - logWarning(message) + logError(message) } func CheckURL(u string, c *gin.Context) []string { @@ -69,7 +72,7 @@ func CheckURL(u string, c *gin.Context) []string { } } errMsg := fmt.Sprintf("%s %s %s %s %s Invalid URL", c.ClientIP(), c.Request.Method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto) - logWarning(errMsg) + logError(errMsg) return nil } diff --git a/rate/rate.go b/rate/rate.go index 85d111e..409b2c1 100644 --- a/rate/rate.go +++ b/rate/rate.go @@ -10,6 +10,8 @@ import ( // 日志输出 var ( logw = logger.Logw + LogDump = logger.LogDump + logDebug = logger.LogDebug logInfo = logger.LogInfo logWarning = logger.LogWarning logError = logger.LogError