Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+100
View File
@@ -0,0 +1,100 @@
package ginzap
import (
"net"
"net/http"
"os"
"runtime/debug"
"strings"
"time"
"91porn-server/common/hevcpull"
"91porn-server/common/log"
"github.com/gin-gonic/gin"
)
func Logger(ctxKeys []string) gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
query := hevcpull.RedactText(c.Request.URL.RawQuery)
c.Next()
end := time.Now()
latency := end.Sub(start)
if len(c.Errors) > 0 {
for _, e := range c.Errors.Errors() {
log.Error(e, log.R(c))
}
} else {
l := []log.Field{
log.R(c),
log.Any("status", c.Writer.Status()),
log.Any("method", c.Request.Method),
log.Any("path", path),
log.Any("query", query),
log.Any("user-agent", c.Request.UserAgent()),
log.Any("time", end.Format("2006-01-02 15:04:05")),
log.Any("latency", latency),
}
for _, k := range ctxKeys {
v, e := c.Get(k)
if e {
l = append(l, log.Any(k, v))
}
}
log.Info(path, l...)
}
}
}
// RecoveryWithZap returns a gin.HandlerFunc (middleware)
// that recovers from any panics and logs requests using uber-go/zap.
// All errors are logged using zap.Error().
// stack means whether output the stack info.
// The stack info is easy to find where the error occurs but the stack info is too large.
func Recovery(stack bool, do func(err interface{})) gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
if do != nil {
do(err)
}
// Check for a broken connection, as it is not really a
// condition that warrants a panic stack trace.
var brokenPipe bool
if ne, ok := err.(*net.OpError); ok {
if se, ok := ne.Err.(*os.SyscallError); ok {
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
brokenPipe = true
}
}
}
// Record request identity without exposing authentication headers or body.
requestFields := []log.Field{
log.R(c),
log.Any("method", c.Request.Method),
log.Any("path", c.Request.URL.Path),
log.Any("panic", err),
}
if brokenPipe {
log.Error(c.Request.URL.Path, requestFields...)
// If the connection is dead, we can't write a status to it.
c.Error(err.(error)) // nolint: errcheck
c.Abort()
return
}
if stack {
requestFields = append(requestFields, log.Any("stack", string(debug.Stack())))
}
log.Error("[Recovery from panic]", requestFields...)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"result": false,
"error": http.StatusText(http.StatusInternalServerError),
})
}
}()
c.Next()
}
}