mirror of
https://github.com/WJQSERVER-STUDIO/ghproxy.git
synced 2026-02-03 16:21:11 +08:00
25w12b
This commit is contained in:
parent
c184e46917
commit
efdf5b0221
8 changed files with 136 additions and 4 deletions
|
|
@ -1,5 +1,12 @@
|
||||||
# 更新日志
|
# 更新日志
|
||||||
|
|
||||||
|
25w12b
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v2.0.8/v2.1.0的预发布版本,请勿在生产环境中使用;
|
||||||
|
- ADD: 加入`timing`中间件记录响应时间
|
||||||
|
- ADD: 加入`loggin`中间件包装日志输出
|
||||||
|
- CHANGE: 更新安全政策, v1和24w版本序列生命周期正式结束
|
||||||
|
|
||||||
25w12a
|
25w12a
|
||||||
---
|
---
|
||||||
- PRE-RELEASE: 此版本是v2.0.8/v2.1.0的预发布版本,请勿在生产环境中使用;
|
- PRE-RELEASE: 此版本是v2.0.8/v2.1.0的预发布版本,请勿在生产环境中使用;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
25w12a
|
25w12b
|
||||||
|
|
@ -6,8 +6,10 @@
|
||||||
|
|
||||||
| 版本 | 是否支持 |
|
| 版本 | 是否支持 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| v1.x.x | :white_check_mark: |
|
| v2.x.x | :white_check_mark: 当前最新版本序列, 受支持 |
|
||||||
| 24w*a/b/c... | :warning: 此为PRE-RELEASE版本,用于开发与测试,可能存在未知的问题 |
|
| v1.x.x | :x: 这些版本已结束生命周期,不再受支持 |
|
||||||
|
| 25w*a/b/c... | :warning: 此为PRE-RELEASE版本,用于开发与测试,可能存在未知的问题 |
|
||||||
|
| 24w*a/b/c... | :warning: 此为PRE-RELEASE版本,用于开发与测试,可能存在未知的问题 生命周期已完全结束 |
|
||||||
| v0.x.x | :x: 这些版本不再受支持 |
|
| v0.x.x | :x: 这些版本不再受支持 |
|
||||||
|
|
||||||
### 用户须知
|
### 用户须知
|
||||||
|
|
|
||||||
34
loggin/loggin.go
Normal file
34
loggin/loggin.go
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
package loggin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ghproxy/timing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/WJQSERVER-STUDIO/go-utils/logger"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
logw = logger.Logw
|
||||||
|
LogDump = logger.LogDump
|
||||||
|
logDebug = logger.LogDebug
|
||||||
|
logInfo = logger.LogInfo
|
||||||
|
logWarning = logger.LogWarning
|
||||||
|
logError = logger.LogError
|
||||||
|
)
|
||||||
|
|
||||||
|
// 日志中间件
|
||||||
|
func Middleware() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
// 处理请求
|
||||||
|
c.Next()
|
||||||
|
|
||||||
|
var timingResults time.Duration
|
||||||
|
|
||||||
|
// 获取计时结果
|
||||||
|
timingResults, _ = timing.Get(c)
|
||||||
|
|
||||||
|
// 记录日志 IP METHOD URL USERAGENT PROTOCOL STATUS TIMING
|
||||||
|
logInfo("%s %s %s %s %d %s ", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Request.UserAgent(), c.Writer.Status(), timingResults)
|
||||||
|
}
|
||||||
|
}
|
||||||
11
main.go
11
main.go
|
|
@ -12,8 +12,10 @@ import (
|
||||||
"ghproxy/api"
|
"ghproxy/api"
|
||||||
"ghproxy/auth"
|
"ghproxy/auth"
|
||||||
"ghproxy/config"
|
"ghproxy/config"
|
||||||
|
"ghproxy/loggin"
|
||||||
"ghproxy/proxy"
|
"ghproxy/proxy"
|
||||||
"ghproxy/rate"
|
"ghproxy/rate"
|
||||||
|
"ghproxy/timing"
|
||||||
|
|
||||||
"github.com/WJQSERVER-STUDIO/go-utils/logger"
|
"github.com/WJQSERVER-STUDIO/go-utils/logger"
|
||||||
|
|
||||||
|
|
@ -124,7 +126,16 @@ func init() {
|
||||||
|
|
||||||
gin.LoggerWithWriter(io.Discard)
|
gin.LoggerWithWriter(io.Discard)
|
||||||
router = gin.New()
|
router = gin.New()
|
||||||
|
|
||||||
|
// 添加recovery中间件
|
||||||
router.Use(gin.Recovery())
|
router.Use(gin.Recovery())
|
||||||
|
|
||||||
|
// 添加log中间件
|
||||||
|
router.Use(loggin.Middleware())
|
||||||
|
|
||||||
|
// 添加计时中间件
|
||||||
|
router.Use(timing.Middleware())
|
||||||
|
|
||||||
//H2C默认值为true,而后遵循cfg.Server.EnableH2C的设置
|
//H2C默认值为true,而后遵循cfg.Server.EnableH2C的设置
|
||||||
if cfg.Server.EnableH2C == "on" {
|
if cfg.Server.EnableH2C == "on" {
|
||||||
router.UseH2C = true
|
router.UseH2C = true
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ func initChunkedHTTPClient() {
|
||||||
|
|
||||||
func ChunkedProxyRequest(c *gin.Context, u string, cfg *config.Config, mode string, runMode string) {
|
func ChunkedProxyRequest(c *gin.Context, u string, cfg *config.Config, mode string, runMode string) {
|
||||||
method := c.Request.Method
|
method := c.Request.Method
|
||||||
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
|
// 发送HEAD请求, 预获取Content-Length
|
||||||
headReq, err := http.NewRequest("HEAD", u, nil)
|
headReq, err := http.NewRequest("HEAD", u, nil)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *rate.IPRateLimiter, runMode string) gin.HandlerFunc {
|
func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *rate.IPRateLimiter, runMode string) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
|
|
||||||
// 限制访问频率
|
// 限制访问频率
|
||||||
if cfg.RateLimit.Enabled {
|
if cfg.RateLimit.Enabled {
|
||||||
|
|
||||||
|
|
|
||||||
78
timing/timing.go
Normal file
78
timing/timing.go
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
package timing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 阶段计时结构(固定数组优化)
|
||||||
|
type timingData struct {
|
||||||
|
phases [8]struct { // 预分配8个阶段存储
|
||||||
|
name string
|
||||||
|
dur time.Duration
|
||||||
|
}
|
||||||
|
count int
|
||||||
|
start time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对象池(内存重用优化)
|
||||||
|
var pool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return new(timingData)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 中间件入口
|
||||||
|
func Middleware() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
// 从池中获取计时器
|
||||||
|
td := pool.Get().(*timingData)
|
||||||
|
td.start = time.Now()
|
||||||
|
td.count = 0
|
||||||
|
|
||||||
|
// 存储到上下文
|
||||||
|
c.Set("timing", td)
|
||||||
|
|
||||||
|
// 请求完成后回收对象
|
||||||
|
defer func() {
|
||||||
|
pool.Put(td)
|
||||||
|
}()
|
||||||
|
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录阶段耗时
|
||||||
|
func Record(c *gin.Context, name string) {
|
||||||
|
if val, exists := c.Get("timing"); exists {
|
||||||
|
td := val.(*timingData)
|
||||||
|
if td.count < len(td.phases) {
|
||||||
|
td.phases[td.count].name = name
|
||||||
|
td.phases[td.count].dur = time.Since(td.start) // 直接记录当前时间
|
||||||
|
td.count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取计时结果(日志输出用)
|
||||||
|
func Get(c *gin.Context) (total time.Duration, phases []struct {
|
||||||
|
Name string
|
||||||
|
Dur time.Duration
|
||||||
|
}) {
|
||||||
|
if val, exists := c.Get("timing"); exists {
|
||||||
|
td := val.(*timingData)
|
||||||
|
for i := 0; i < td.count; i++ {
|
||||||
|
phases = append(phases, struct {
|
||||||
|
Name string
|
||||||
|
Dur time.Duration
|
||||||
|
}{
|
||||||
|
Name: td.phases[i].name,
|
||||||
|
Dur: td.phases[i].dur,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
total = time.Since(td.start)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue