Files
gateway/internal/plugin/ratelimit/router/gin/tokenextractor.go
zeekayandHanzo Dev 765aa24834 fix(vendor): the two defects go vet finds now the engine is ours
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]>
2026-07-25 15:01:33 -07:00

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
}
}