Compare commits
5 Commits
5f831c7005
...
388a2c57e1
Author | SHA1 | Date | |
---|---|---|---|
388a2c57e1 | |||
6a8179b316 | |||
7f5da8e5e1 | |||
e2ac9a7704 | |||
9ad207f6c9 |
4
go.mod
4
go.mod
@ -5,12 +5,11 @@ go 1.20
|
||||
require (
|
||||
github.com/casbin/casbin/v2 v2.70.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-redis/redis v6.15.9+incompatible
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/hibiken/asynq v0.24.1
|
||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
||||
github.com/mattn/go-runewidth v0.0.14
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/redis/go-redis/v9 v9.2.1
|
||||
github.com/rs/xid v1.5.0
|
||||
github.com/stretchr/testify v1.8.3
|
||||
go.mongodb.org/mongo-driver v1.11.7
|
||||
@ -49,7 +48,6 @@ require (
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/redis/go-redis/v9 v9.2.1 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
|
13
go.sum
13
go.sum
@ -1,10 +1,8 @@
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
|
||||
github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
|
||||
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
@ -22,7 +20,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
@ -36,10 +33,6 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||
@ -91,16 +84,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/redis/go-redis/v9 v9.0.3 h1:+7mmR26M0IvyLxGZUHxu4GiBkJkVDid0Un+j4ScYu4k=
|
||||
github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
|
||||
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg=
|
||||
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
@ -209,8 +198,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -5,13 +5,13 @@
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
package middleware
|
||||
package cors
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"git.hexq.cn/tiglog/golib/helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func NewCors(origins []string) gin.HandlerFunc {
|
@ -5,7 +5,7 @@
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
package middleware_test
|
||||
package cors_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -13,15 +13,15 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"git.hexq.cn/tiglog/golib/gtest"
|
||||
"git.hexq.cn/tiglog/golib/middleware"
|
||||
"git.hexq.cn/tiglog/golib/gweb/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func newTestRouter(origins []string) *gin.Engine {
|
||||
gin.SetMode(gin.TestMode)
|
||||
router := gin.New()
|
||||
router.Use(middleware.NewCors(origins))
|
||||
router.Use(cors.NewCors(origins))
|
||||
router.GET("/", func(c *gin.Context) {
|
||||
c.String(http.StatusOK, "get")
|
||||
})
|
@ -5,7 +5,7 @@
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
package middleware
|
||||
package ginlog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -32,8 +32,7 @@ func GinLogger(logfile string) gin.HandlerFunc {
|
||||
if latency > time.Minute {
|
||||
latency = latency.Truncate(time.Second)
|
||||
}
|
||||
|
||||
log.Info("GIN request",
|
||||
fields := []logger.Field{
|
||||
logger.String("start", start.Format(time.RFC3339)),
|
||||
logger.Int("status", c.Writer.Status()),
|
||||
logger.String("latency", fmt.Sprintf("%s", latency)),
|
||||
@ -43,6 +42,11 @@ func GinLogger(logfile string) gin.HandlerFunc {
|
||||
logger.String("clientIP", c.ClientIP()),
|
||||
logger.String("userAgent", c.Request.UserAgent()),
|
||||
logger.String("error", c.Errors.ByType(gin.ErrorTypePrivate).String()),
|
||||
)
|
||||
}
|
||||
if requestID := c.Writer.Header().Get("X-Request-Id"); requestID != "" {
|
||||
fields = append(fields, logger.String("request_id", requestID))
|
||||
}
|
||||
|
||||
log.Info("GIN request", fields...)
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
package middleware
|
||||
package ginlog
|
||||
|
||||
import (
|
||||
"errors"
|
46
gweb/gzip/gzip.go
Normal file
46
gweb/gzip/gzip.go
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// gzip.go
|
||||
// Copyright (C) 2023 tiglog <me@tiglog.com>
|
||||
//
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
package gzip
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
BestCompression = gzip.BestCompression
|
||||
BestSpeed = gzip.BestSpeed
|
||||
DefaultCompression = gzip.DefaultCompression
|
||||
NoCompression = gzip.NoCompression
|
||||
)
|
||||
|
||||
func Gzip(level int, options ...Option) gin.HandlerFunc {
|
||||
return newGzipHandler(level, options...).Handle
|
||||
}
|
||||
|
||||
type gzipWriter struct {
|
||||
gin.ResponseWriter
|
||||
writer *gzip.Writer
|
||||
}
|
||||
|
||||
func (g *gzipWriter) WriteString(s string) (int, error) {
|
||||
g.Header().Del("Content-Length")
|
||||
return g.writer.Write([]byte(s))
|
||||
}
|
||||
|
||||
func (g *gzipWriter) Write(data []byte) (int, error) {
|
||||
g.Header().Del("Content-Length")
|
||||
return g.writer.Write(data)
|
||||
}
|
||||
|
||||
// Fix: https://github.com/mholt/caddy/issues/38
|
||||
func (g *gzipWriter) WriteHeader(code int) {
|
||||
g.Header().Del("Content-Length")
|
||||
g.ResponseWriter.WriteHeader(code)
|
||||
}
|
90
gweb/gzip/handler.go
Normal file
90
gweb/gzip/handler.go
Normal file
@ -0,0 +1,90 @@
|
||||
//
|
||||
// handler.go
|
||||
// Copyright (C) 2023 tiglog <me@tiglog.com>
|
||||
//
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
package gzip
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type gzipHandler struct {
|
||||
*Options
|
||||
gzPool sync.Pool
|
||||
}
|
||||
|
||||
func newGzipHandler(level int, options ...Option) *gzipHandler {
|
||||
handler := &gzipHandler{
|
||||
Options: DefaultOptions,
|
||||
gzPool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
gz, err := gzip.NewWriterLevel(io.Discard, level)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return gz
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, setter := range options {
|
||||
setter(handler.Options)
|
||||
}
|
||||
return handler
|
||||
}
|
||||
|
||||
func (g *gzipHandler) Handle(c *gin.Context) {
|
||||
if fn := g.DecompressFn; fn != nil && c.Request.Header.Get("Content-Encoding") == "gzip" {
|
||||
fn(c)
|
||||
}
|
||||
|
||||
if !g.shouldCompress(c.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
gz := g.gzPool.Get().(*gzip.Writer)
|
||||
defer g.gzPool.Put(gz)
|
||||
defer gz.Reset(io.Discard)
|
||||
gz.Reset(c.Writer)
|
||||
|
||||
c.Header("Content-Encoding", "gzip")
|
||||
c.Header("Vary", "Accept-Encoding")
|
||||
c.Writer = &gzipWriter{c.Writer, gz}
|
||||
defer func() {
|
||||
gz.Close()
|
||||
c.Header("Content-Length", fmt.Sprint(c.Writer.Size()))
|
||||
}()
|
||||
c.Next()
|
||||
}
|
||||
|
||||
func (g *gzipHandler) shouldCompress(req *http.Request) bool {
|
||||
if !strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") ||
|
||||
strings.Contains(req.Header.Get("Connection"), "Upgrade") ||
|
||||
strings.Contains(req.Header.Get("Accept"), "text/event-stream") {
|
||||
return false
|
||||
}
|
||||
|
||||
extension := filepath.Ext(req.URL.Path)
|
||||
if g.ExcludedExtensions.Contains(extension) {
|
||||
return false
|
||||
}
|
||||
|
||||
if g.ExcludedPaths.Contains(req.URL.Path) {
|
||||
return false
|
||||
}
|
||||
if g.ExcludedPathesRegexs.Contains(req.URL.Path) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
123
gweb/gzip/options.go
Normal file
123
gweb/gzip/options.go
Normal file
@ -0,0 +1,123 @@
|
||||
//
|
||||
// options.go
|
||||
// Copyright (C) 2023 tiglog <me@tiglog.com>
|
||||
//
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
package gzip
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultExcludedExtentions = NewExcludedExtensions([]string{
|
||||
".png", ".gif", ".jpeg", ".jpg",
|
||||
})
|
||||
DefaultOptions = &Options{
|
||||
ExcludedExtensions: DefaultExcludedExtentions,
|
||||
}
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
ExcludedExtensions ExcludedExtensions
|
||||
ExcludedPaths ExcludedPaths
|
||||
ExcludedPathesRegexs ExcludedPathesRegexs
|
||||
DecompressFn func(c *gin.Context)
|
||||
}
|
||||
|
||||
type Option func(*Options)
|
||||
|
||||
func WithExcludedExtensions(args []string) Option {
|
||||
return func(o *Options) {
|
||||
o.ExcludedExtensions = NewExcludedExtensions(args)
|
||||
}
|
||||
}
|
||||
|
||||
func WithExcludedPaths(args []string) Option {
|
||||
return func(o *Options) {
|
||||
o.ExcludedPaths = NewExcludedPaths(args)
|
||||
}
|
||||
}
|
||||
|
||||
func WithExcludedPathsRegexs(args []string) Option {
|
||||
return func(o *Options) {
|
||||
o.ExcludedPathesRegexs = NewExcludedPathesRegexs(args)
|
||||
}
|
||||
}
|
||||
|
||||
func WithDecompressFn(decompressFn func(c *gin.Context)) Option {
|
||||
return func(o *Options) {
|
||||
o.DecompressFn = decompressFn
|
||||
}
|
||||
}
|
||||
|
||||
// Using map for better lookup performance
|
||||
type ExcludedExtensions map[string]bool
|
||||
|
||||
func NewExcludedExtensions(extensions []string) ExcludedExtensions {
|
||||
res := make(ExcludedExtensions)
|
||||
for _, e := range extensions {
|
||||
res[e] = true
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (e ExcludedExtensions) Contains(target string) bool {
|
||||
_, ok := e[target]
|
||||
return ok
|
||||
}
|
||||
|
||||
type ExcludedPaths []string
|
||||
|
||||
func NewExcludedPaths(paths []string) ExcludedPaths {
|
||||
return ExcludedPaths(paths)
|
||||
}
|
||||
|
||||
func (e ExcludedPaths) Contains(requestURI string) bool {
|
||||
for _, path := range e {
|
||||
if strings.HasPrefix(requestURI, path) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ExcludedPathesRegexs []*regexp.Regexp
|
||||
|
||||
func NewExcludedPathesRegexs(regexs []string) ExcludedPathesRegexs {
|
||||
result := make([]*regexp.Regexp, len(regexs))
|
||||
for i, reg := range regexs {
|
||||
result[i] = regexp.MustCompile(reg)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (e ExcludedPathesRegexs) Contains(requestURI string) bool {
|
||||
for _, reg := range e {
|
||||
if reg.MatchString(requestURI) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func DefaultDecompressHandle(c *gin.Context) {
|
||||
if c.Request.Body == nil {
|
||||
return
|
||||
}
|
||||
r, err := gzip.NewReader(c.Request.Body)
|
||||
if err != nil {
|
||||
_ = c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
c.Request.Header.Del("Content-Encoding")
|
||||
c.Request.Header.Del("Content-Length")
|
||||
c.Request.Body = r
|
||||
}
|
93
gweb/gzip/readme.md
Normal file
93
gweb/gzip/readme.md
Normal file
@ -0,0 +1,93 @@
|
||||
# GZIP gin's middleware
|
||||
|
||||
|
||||
Gin middleware to enable `GZIP` support.
|
||||
|
||||
## Usage
|
||||
|
||||
Customized Excluded Extensions
|
||||
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := gin.Default()
|
||||
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedExtensions([]string{".pdf", ".mp4"})))
|
||||
r.GET("/ping", func(c *gin.Context) {
|
||||
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
|
||||
})
|
||||
|
||||
// Listen and Server in 0.0.0.0:8080
|
||||
if err := r.Run(":8080"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Customized Excluded Paths
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := gin.Default()
|
||||
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{"/api/"})))
|
||||
r.GET("/ping", func(c *gin.Context) {
|
||||
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
|
||||
})
|
||||
|
||||
// Listen and Server in 0.0.0.0:8080
|
||||
if err := r.Run(":8080"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Customized Excluded Paths
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := gin.Default()
|
||||
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPathsRegexs([]string{".*"})))
|
||||
r.GET("/ping", func(c *gin.Context) {
|
||||
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
|
||||
})
|
||||
|
||||
// Listen and Server in 0.0.0.0:8080
|
||||
if err := r.Run(":8080"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
41
gweb/requestid/options.go
Normal file
41
gweb/requestid/options.go
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// options.go
|
||||
// Copyright (C) 2023 tiglog <me@tiglog.com>
|
||||
//
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
package requestid
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
// Option for queue system
|
||||
type Option func(*config)
|
||||
|
||||
type (
|
||||
Generator func() string
|
||||
Handler func(c *gin.Context, requestID string)
|
||||
)
|
||||
|
||||
type HeaderStrKey string
|
||||
|
||||
// WithGenerator set generator function
|
||||
func WithGenerator(g Generator) Option {
|
||||
return func(cfg *config) {
|
||||
cfg.generator = g
|
||||
}
|
||||
}
|
||||
|
||||
// WithCustomHeaderStrKey set custom header key for request id
|
||||
func WithCustomHeaderStrKey(s HeaderStrKey) Option {
|
||||
return func(cfg *config) {
|
||||
cfg.headerKey = s
|
||||
}
|
||||
}
|
||||
|
||||
// WithHandler set handler function for request id with context
|
||||
func WithHandler(handler Handler) Option {
|
||||
return func(cfg *config) {
|
||||
cfg.handler = handler
|
||||
}
|
||||
}
|
62
gweb/requestid/reqid.go
Normal file
62
gweb/requestid/reqid.go
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// reqid.go
|
||||
// Copyright (C) 2023 tiglog <me@tiglog.com>
|
||||
//
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
package requestid
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rs/xid"
|
||||
)
|
||||
|
||||
var headerXRequestID string
|
||||
|
||||
// Config defines the config for RequestID middleware
|
||||
type config struct {
|
||||
// Generator defines a function to generate an ID.
|
||||
// Optional. Default: func() string {
|
||||
// return xid.New().String()
|
||||
// }
|
||||
generator Generator
|
||||
headerKey HeaderStrKey
|
||||
handler Handler
|
||||
}
|
||||
|
||||
// New initializes the RequestID middleware.
|
||||
func New(opts ...Option) gin.HandlerFunc {
|
||||
cfg := &config{
|
||||
generator: func() string {
|
||||
return xid.New().String()
|
||||
},
|
||||
headerKey: "X-Request-ID",
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(cfg)
|
||||
}
|
||||
|
||||
headerXRequestID = string(cfg.headerKey)
|
||||
|
||||
return func(c *gin.Context) {
|
||||
// Get id from request
|
||||
rid := c.GetHeader(headerXRequestID)
|
||||
if rid == "" {
|
||||
rid = cfg.generator()
|
||||
c.Request.Header.Add(headerXRequestID, rid)
|
||||
}
|
||||
if cfg.handler != nil {
|
||||
cfg.handler(c, rid)
|
||||
}
|
||||
// Set the id to ensure that the requestid is in the response
|
||||
c.Header(headerXRequestID, rid)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the request identifier
|
||||
func Get(c *gin.Context) string {
|
||||
return c.GetHeader(headerXRequestID)
|
||||
}
|
@ -95,6 +95,9 @@ func Default() *Logger { return std }
|
||||
func ReplaceDefault(l *Logger) { std = l }
|
||||
|
||||
func SetLevel(level Level) { std.SetLevel(level) }
|
||||
func With(fields ...Field) {
|
||||
std.l.With(fields...)
|
||||
}
|
||||
|
||||
func Debug(msg string, fields ...Field) { std.Debug(msg, fields...) }
|
||||
func Info(msg string, fields ...Field) { std.Info(msg, fields...) }
|
||||
|
Loading…
Reference in New Issue
Block a user