middleware

package
v1.11.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 17, 2024 License: MIT Imports: 23 Imported by: 0

README

middleware

Gin middleware plugin.


Example of use

logging middleware

You can set the maximum length for printing, add a request id field, ignore print path, customize zap log.

    import "github.com/zhufuyi/sponge/pkg/gin/middleware"

    r := gin.Default()

    // default
    r.Use(middleware.Logging()) // simplified logging using middleware.SimpleLog()

    // --- or ---

    // custom
    r.Use(middleware.Logging(    // simplified logging using middleware.SimpleLog(WithRequestIDFromHeader())
        middleware.WithMaxLen(400),
        WithRequestIDFromHeader(),
        //WithRequestIDFromContext(),
        //middleware.WithLog(log), // custom zap log
        //middleware.WithIgnoreRoutes("/hello"),
    ))

Allow cross-domain requests middleware

    import "github.com/zhufuyi/sponge/pkg/gin/middleware"

    r := gin.Default()
    r.Use(middleware.Cors())

rate limiter middleware

Adaptive flow limitation based on hardware resources.

    import "github.com/zhufuyi/sponge/pkg/gin/middleware"

    r := gin.Default()

    // default
    r.Use(middleware.RateLimit())

    // --- or ---

    // custom
    r.Use(middleware.RateLimit(
        WithWindow(time.Second*10),
        WithBucket(100),
        WithCPUThreshold(100),
        WithCPUQuota(0.5),
    ))

Circuit Breaker middleware

    import "github.com/zhufuyi/sponge/pkg/gin/middleware"

    r := gin.Default()
    r.Use(middleware.CircuitBreaker(
        //middleware.WithValidCode(http.StatusRequestTimeout), // add error code 408 for circuit breaker
        //middleware.WithDegradeHandler(handler), // add custom degrade handler
    ))

jwt authorization middleware

standard authorization
import "github.com/zhufuyi/sponge/pkg/jwt"
import "github.com/zhufuyi/sponge/pkg/gin/middleware"

func main() {
    r := gin.Default()

    r.POST("/user/login", Login)
    r.GET("/user/:id", middleware.Auth(), h.GetByID) // do not get claims
    // r.GET("/user/:id", middleware.Auth(middleware.WithVerify(adminVerify)), h.GetByID) // get claims and check

    r.Run(serverAddr)
}

func adminVerify(claims *jwt.Claims, tokenTail10 string, c *gin.Context) error {
    if claims.Name != "admin" {
        return errors.New("verify failed")
    }

    // token := getToken(claims.UID) // from cache or database
    // if tokenTail10 != token[len(token)-10:] { return err }

    return nil
}

func Login(c *gin.Context) {
    // generate token
    token, err := jwt.GenerateToken("123", "admin")
    // save token
}

custom authorization
import "github.com/zhufuyi/sponge/pkg/jwt"
import "github.com/zhufuyi/sponge/pkg/gin/middleware"

func main() {
    r := gin.Default()

    r.POST("/user/login", Login)
    r.GET("/user/:id", middleware.AuthCustom(verify), h.GetByID) // get claims and check

    r.Run(serverAddr)
}

// custom verify example
func verify(claims *jwt.CustomClaims, tokenTail10 string, c *gin.Context) error {
    err := errors.New("verify failed")

    token, fields := getToken(id) // from cache or database
    // if tokenTail10 != token[len(token)-10:] { return err }

    id, exist := claims.GetUint64("id")
    if !exist || id != fields["id"].(uint64) { return err }

    name, exist := claims.GetString("name")
    if !exist || name != fields["name"].(string) { return err }

    age, exist := claims.GetInt("age")
    if !exist || age != fields["age"].(int) { return err }

    return nil
}

func Login(c *gin.Context) {
    // generate token
    fields := jwt.KV{"id": uint64(123), "name": "tom", "age": 10}
    token, err := jwt.GenerateCustomToken(fields)
    // save token and fields
}

tracing middleware

import "github.com/zhufuyi/sponge/pkg/tracer"
import "github.com/zhufuyi/sponge/pkg/gin/middleware"

func InitTrace(serviceName string) {
	exporter, err := tracer.NewJaegerAgentExporter("192.168.3.37", "6831")
	if err != nil {
		panic(err)
	}

	resource := tracer.NewResource(
		tracer.WithServiceName(serviceName),
		tracer.WithEnvironment("dev"),
		tracer.WithServiceVersion("demo"),
	)

	tracer.Init(exporter, resource) // collect all by default
}

func NewRouter(
	r := gin.Default()
	r.Use(middleware.Tracing("your-service-name"))

	// ......
)

// if necessary, you can create a span in the program
func SpanDemo(serviceName string, spanName string, ctx context.Context) {
	_, span := otel.Tracer(serviceName).Start(
		ctx, spanName,
		trace.WithAttributes(attribute.String(spanName, time.Now().String())),
	)
	defer span.End()

	// ......
}

Metrics middleware

    import "github.com/zhufuyi/sponge/pkg/gin/middleware/metrics"

    r := gin.Default()

    r.Use(metrics.Metrics(r,
        //metrics.WithMetricsPath("/demo/metrics"), // default is /metrics
        metrics.WithIgnoreStatusCodes(http.StatusNotFound), // ignore status codes
        //metrics.WithIgnoreRequestMethods(http.MethodHead),  // ignore request methods
        //metrics.WithIgnoreRequestPaths("/ping", "/health"), // ignore request paths
    ))

Request id

    import "github.com/zhufuyi/sponge/pkg/gin/middleware"

    // Default request id
    r := gin.Default()
    r.Use(middleware.RequestID())

    // --- or ---

    // Customized request id key
    //r.User(middleware.RequestID(
    //    middleware.WithContextRequestIDKey("your ctx request id key"), // default is request_id
    //    middleware.WithHeaderRequestIDKey("your header request id key"), // default is X-Request-Id
    //))
    // If you change the ContextRequestIDKey, you have to set the same key name if you want to print the request id in the mysql logs as well.
    // example: 
    // db, err := mysql.Init(dsn,
        // mysql.WithLogRequestIDKey("your ctx request id key"),  // print request_id
        // ...
    // )

Timeout

    import "github.com/zhufuyi/sponge/pkg/gin/middleware"

    r := gin.Default()

    // way1: global set timeout
    r.Use(middleware.Timeout(time.Second*5))

    // --- or ---

    // way2: router set timeout
    r.GET("/userExample/:id", middleware.Timeout(time.Second*3), h.GetByID)

    // Note: If timeout is set both globally and in the router, the minimum timeout prevails

Documentation

Overview

Package middleware is gin middleware plugin.

Index

Constants

View Source
const (
	// HeaderAuthorizationKey http header authorization key
	HeaderAuthorizationKey = "Authorization"
)

Variables

View Source
var (
	// ContextRequestIDKey request id for context
	ContextRequestIDKey = "request_id"

	// HeaderXRequestIDKey header request id key
	HeaderXRequestIDKey = "X-Request-Id"
)
View Source
var ErrLimitExceed = rl.ErrLimitExceed

ErrLimitExceed is returned when the rate limiter is triggered and the request is rejected due to limit exceeded.

ErrNotAllowed error not allowed.

View Source
var RequestHeaderKey = "request_header_key"

RequestHeaderKey request header key

RequestIDKey request_id

Functions

func AdaptCtx added in v1.8.5

func AdaptCtx(ctx context.Context) (*gin.Context, context.Context)

AdaptCtx adapt context, if ctx is gin.Context, return gin.Context and context of the transformation

func Auth

func Auth(opts ...JwtOption) gin.HandlerFunc

Auth authorization

func AuthCustom added in v1.5.4

func AuthCustom(verify VerifyCustomFn, opts ...JwtOption) gin.HandlerFunc

AuthCustom custom authentication

func CircuitBreaker

func CircuitBreaker(opts ...CircuitBreakerOption) gin.HandlerFunc

CircuitBreaker a circuit breaker middleware

func Cors

func Cors() gin.HandlerFunc

Cors cross domain

func CtxRequestID added in v1.2.0

func CtxRequestID(ctx context.Context) string

CtxRequestID get request id from context.Context

func CtxRequestIDField added in v1.2.0

func CtxRequestIDField(ctx context.Context) zap.Field

CtxRequestIDField get request id field from context.Context

func GCtxRequestID added in v1.2.0

func GCtxRequestID(c *gin.Context) string

GCtxRequestID get request id from gin.Context

func GCtxRequestIDField added in v1.2.0

func GCtxRequestIDField(c *gin.Context) zap.Field

GCtxRequestIDField get request id field from gin.Context

func GetFromCtx added in v1.5.6

func GetFromCtx(ctx context.Context, key string) interface{}

GetFromCtx get value from context

func GetFromHeader added in v1.5.6

func GetFromHeader(ctx context.Context, key string) string

GetFromHeader get value from header

func GetFromHeaders added in v1.5.6

func GetFromHeaders(ctx context.Context, key string) []string

GetFromHeaders get values from header

func HeaderRequestID added in v1.2.0

func HeaderRequestID(c *gin.Context) string

HeaderRequestID get request id from the header

func HeaderRequestIDField added in v1.2.0

func HeaderRequestIDField(c *gin.Context) zap.Field

HeaderRequestIDField get request id field from header

func Logging

func Logging(opts ...Option) gin.HandlerFunc

Logging print request and response info

func RateLimit

func RateLimit(opts ...RateLimitOption) gin.HandlerFunc

RateLimit an adaptive rate limiter middleware

func RequestID

func RequestID(opts ...RequestIDOption) gin.HandlerFunc

RequestID is an interceptor that injects a 'request id' into the context and request/response header of each request.

func SimpleLog added in v1.8.0

func SimpleLog(opts ...Option) gin.HandlerFunc

SimpleLog print response info

func Timeout added in v1.8.0

func Timeout(d time.Duration) gin.HandlerFunc

Timeout request time out

func Tracing

func Tracing(serviceName string, opts ...TraceOption) gin.HandlerFunc

Tracing returns interceptor that will trace incoming requests. The service parameter should describe the name of the (virtual) server handling the request.

func WrapCtx added in v1.5.6

func WrapCtx(c *gin.Context) context.Context

WrapCtx wrap context, put the Keys and Header of gin.Context into context

Types

type CircuitBreakerOption

type CircuitBreakerOption func(*circuitBreakerOptions)

CircuitBreakerOption set the circuit breaker circuitBreakerOptions.

func WithDegradeHandler added in v1.9.0

func WithDegradeHandler(handler func(c *gin.Context)) CircuitBreakerOption

WithDegradeHandler set degrade handler function

func WithGroup

func WithGroup(g *group.Group) CircuitBreakerOption

WithGroup with circuit breaker group. NOTE: implements generics circuitbreaker.CircuitBreaker

func WithValidCode added in v1.4.2

func WithValidCode(code ...int) CircuitBreakerOption

WithValidCode http code to mark failed

type CtxKeyString added in v1.5.3

type CtxKeyString string

CtxKeyString for context.WithValue key type

type JwtOption added in v1.5.4

type JwtOption func(*jwtOptions)

JwtOption set the jwt options.

func WithSwitchHTTPCode added in v1.5.4

func WithSwitchHTTPCode() JwtOption

WithSwitchHTTPCode switch to http code

func WithVerify added in v1.5.4

func WithVerify(verify VerifyFn) JwtOption

WithVerify set verify function

type Option

type Option func(*options)

Option set the gin logger options.

func WithIgnoreRoutes

func WithIgnoreRoutes(routes ...string) Option

WithIgnoreRoutes no logger content routes

func WithLog

func WithLog(log *zap.Logger) Option

WithLog set log

func WithMaxLen

func WithMaxLen(maxLen int) Option

WithMaxLen logger content max length

func WithRequestIDFromContext

func WithRequestIDFromContext() Option

WithRequestIDFromContext name is field in context, default value is request_id

func WithRequestIDFromHeader

func WithRequestIDFromHeader() Option

WithRequestIDFromHeader name is field in header, default value is X-Request-Id

type RateLimitOption

type RateLimitOption func(*rateLimitOptions)

RateLimitOption set the rate limits rateLimitOptions.

func WithBucket

func WithBucket(b int) RateLimitOption

WithBucket with bucket size.

func WithCPUQuota

func WithCPUQuota(quota float64) RateLimitOption

WithCPUQuota with real cpu quota(if it can not collect from process correct);

func WithCPUThreshold

func WithCPUThreshold(threshold int64) RateLimitOption

WithCPUThreshold with cpu threshold

func WithWindow

func WithWindow(d time.Duration) RateLimitOption

WithWindow with window size.

type RequestIDOption added in v1.5.6

type RequestIDOption func(*requestIDOptions)

RequestIDOption set the request id options.

func WithContextRequestIDKey added in v1.5.6

func WithContextRequestIDKey(key string) RequestIDOption

WithContextRequestIDKey set context request id key, minimum length of 4

func WithHeaderRequestIDKey added in v1.5.6

func WithHeaderRequestIDKey(key string) RequestIDOption

WithHeaderRequestIDKey set header request id key, minimum length of 4

type TraceOption

type TraceOption func(*traceConfig)

TraceOption specifies instrumentation configuration options.

func WithPropagators

func WithPropagators(propagators propagation.TextMapPropagator) TraceOption

WithPropagators specifies propagators to use for extracting information from the HTTP requests. If none are specified, global ones will be used.

func WithTracerProvider

func WithTracerProvider(provider oteltrace.TracerProvider) TraceOption

WithTracerProvider specifies a tracer provider to use for creating a tracer. If none is specified, the global provider is used.

type VerifyCustomFn added in v1.5.4

type VerifyCustomFn func(claims *jwt.CustomClaims, tokenTail10 string, c *gin.Context) error

VerifyCustomFn verify custom function, tokenTail10 is the last 10 characters of the token.

type VerifyFn added in v1.5.4

type VerifyFn func(claims *jwt.Claims, tokenTail10 string, c *gin.Context) error

VerifyFn verify function, tokenTail10 is the last 10 characters of the token.

Directories

Path Synopsis
Package metrics is gin metrics library, collect five metrics, "uptime", "http_request_count_total", "http_request_duration_seconds", "http_request_size_bytes", "http_response_size_bytes".
Package metrics is gin metrics library, collect five metrics, "uptime", "http_request_count_total", "http_request_duration_seconds", "http_request_size_bytes", "http_response_size_bytes".

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL