mirror of
https://github.com/hanzoai/gateway.git
synced 2026-11-02 23:52:23 +00:00
Vet does not analyse module dependencies, so these sat unreported for as long as the engine lived in github.com/krakend/*. Folding it in put the code under our own `go vet ./...` and both surfaced immediately. Both are real, both fixes are behaviour-preserving, and neither is cosmetic: binder/context.go — Context.error passed a runtime string as the FORMAT argument of the printf-style LState.RaiseError. That string carries Lua script and host error text, so a '%' anywhere in a message is read as a verb: the error gets mangled and %!v(MISSING) is emitted from input an attacker can influence. Now passed as an argument. ratelimit/router/gin — a `return` after a switch whose every arm (including default) already returns. Unreachable; deleted. Also repoints two doc comments that still named upstream import paths, so the package docs describe where the code actually lives. Nothing else in internal/ deviates from upstream: 196 of 197 files remain byte-identical under the mechanical import rewrite, the lone exception being the bloomfilter subpackage rename from the previous commit. Re-run the check before any upstream re-sync so these four edits are carried forward deliberately rather than silently reverted. go vet ./... and go vet -tags legacy ./... -> both clean Co-authored-by: Hanzo Dev <[email protected]>
61 lines
1.9 KiB
Go
61 lines
1.9 KiB
Go
package gin
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/hanzoai/gateway/v2/internal/plugin/ratelimit/router"
|
|
)
|
|
|
|
var ErrNotFound = errors.New("not found")
|
|
|
|
// TokenExtractor defines the interface of the functions to use in order to extract a token for each request
|
|
type TokenExtractor func(*gin.Context) string
|
|
|
|
// IPTokenExtractor extracts the IP of the request
|
|
func IPTokenExtractor(c *gin.Context) string { return c.ClientIP() }
|
|
|
|
// NewIPTokenExtractor generates an IP TokenExtractor checking first for the contents of the passed header.
|
|
// If nothing is found there, the regular IPTokenExtractor function is called.
|
|
func NewIPTokenExtractor(header string) TokenExtractor {
|
|
if header == "" {
|
|
return IPTokenExtractor
|
|
}
|
|
return func(c *gin.Context) string {
|
|
if clientIP := strings.TrimSpace(strings.Split(c.Request.Header.Get(header), ",")[0]); clientIP != "" {
|
|
ip := strings.Split(clientIP, ":")[0]
|
|
if parsedIP := net.ParseIP(ip); parsedIP != nil {
|
|
return ip
|
|
}
|
|
}
|
|
return IPTokenExtractor(c)
|
|
}
|
|
}
|
|
|
|
// HeaderTokenExtractor returns a TokenExtractor that looks for the value of the designed header
|
|
func HeaderTokenExtractor(header string) TokenExtractor {
|
|
return func(c *gin.Context) string { return c.Request.Header.Get(header) }
|
|
}
|
|
|
|
// ParamTokenExtractor returns a TokenExtractor that uses a param a token
|
|
func ParamTokenExtractor(param string) TokenExtractor {
|
|
return func(c *gin.Context) string { return c.Param(param) }
|
|
}
|
|
|
|
// TokenExtractorFromCfg selects the token extractor to use from the input config
|
|
func TokenExtractorFromCfg(cfg router.Config) (TokenExtractor, error) {
|
|
switch strategy := strings.ToLower(cfg.Strategy); strategy {
|
|
case "ip":
|
|
return NewIPTokenExtractor(cfg.Key), nil
|
|
case "header":
|
|
return HeaderTokenExtractor(cfg.Key), nil
|
|
case "param":
|
|
return ParamTokenExtractor(cfg.Key), nil
|
|
default:
|
|
return nil, ErrNotFound
|
|
}
|
|
}
|