Skip to content

Commit

Permalink
canary middleware support config labels map
Browse files Browse the repository at this point in the history
  • Loading branch information
zensh committed Jul 10, 2020
1 parent d8afb49 commit 9e24f89
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 9 deletions.
25 changes: 16 additions & 9 deletions pkg/config/dynamic/middlewares.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,13 +508,20 @@ func (c *ClientTLS) CreateTLSConfig() (*tls.Config, error) {

// Canary middleware settings.
type Canary struct {
Product string `json:"product,omitempty" toml:"product,omitempty" yaml:"product,omitempty" export:"true"`
Server string `json:"server,omitempty" toml:"server,omitempty" yaml:"server,omitempty" export:"true"`
UIDCookies []string `json:"uidCookies,omitempty" toml:"uidCookies,omitempty" yaml:"uidCookies,omitempty" export:"true"`
AddRequestID bool `json:"addRequestID,omitempty" toml:"addRequestID,omitempty" yaml:"addRequestID,omitempty" export:"true"`
CanaryResponseHeader bool `json:"canaryResponseHeader,omitempty" toml:"canaryResponseHeader,omitempty" yaml:"canaryResponseHeader,omitempty" export:"true"`
MaxCacheSize int `json:"maxCacheSize,omitempty" toml:"maxCacheSize,omitempty" yaml:"maxCacheSize,omitempty" export:"true"`
CacheExpiration types.Duration `json:"cacheExpiration,omitempty" toml:"cacheExpiration,omitempty" yaml:"cacheExpiration,omitempty" export:"true"`
CacheCleanDuration types.Duration `json:"cacheCleanDuration,omitempty" toml:"cacheCleanDuration,omitempty" yaml:"cacheCleanDuration,omitempty" export:"true"`
Sticky *Sticky `json:"sticky,omitempty" toml:"sticky,omitempty" yaml:"sticky,omitempty" export:"true"`
Product string `json:"product,omitempty" toml:"product,omitempty" yaml:"product,omitempty"`
Server string `json:"server,omitempty" toml:"server,omitempty" yaml:"server,omitempty"`
UIDCookies []string `json:"uidCookies,omitempty" toml:"uidCookies,omitempty" yaml:"uidCookies,omitempty"`
AddRequestID bool `json:"addRequestID,omitempty" toml:"addRequestID,omitempty" yaml:"addRequestID,omitempty"`
CanaryResponseHeader bool `json:"canaryResponseHeader,omitempty" toml:"canaryResponseHeader,omitempty" yaml:"canaryResponseHeader,omitempty"`
MaxCacheSize int `json:"maxCacheSize,omitempty" toml:"maxCacheSize,omitempty" yaml:"maxCacheSize,omitempty"`
CacheExpiration types.Duration `json:"cacheExpiration,omitempty" toml:"cacheExpiration,omitempty" yaml:"cacheExpiration,omitempty"`
CacheCleanDuration types.Duration `json:"cacheCleanDuration,omitempty" toml:"cacheCleanDuration,omitempty" yaml:"cacheCleanDuration,omitempty"`
Sticky *Sticky `json:"sticky,omitempty" toml:"sticky,omitempty" yaml:"sticky,omitempty"`
LabelsMap *LabelsMap `json:"labelsMap,omitempty" toml:"labelsMap,omitempty" yaml:"labelsMap,omitempty"`
}

// LabelsMap get canary labels from header with map
type LabelsMap struct {
RequestHeaderName string `json:"requestHeaderName,omitempty" toml:"requestHeaderName,omitempty" yaml:"requestHeaderName,omitempty"`
Labels map[string]string `json:"labels,omitempty" toml:"labels,omitempty" yaml:"labels,omitempty"`
}
20 changes: 20 additions & 0 deletions pkg/middlewares/canary/canary.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type Canary struct {
loadLabels bool
ls *LabelStore
sticky *dynamic.Sticky
labelsMap *dynamic.LabelsMap
next http.Handler
}

Expand All @@ -71,6 +72,12 @@ func New(ctx context.Context, next http.Handler, cfg dynamic.Canary, name string
cfg.MaxCacheSize = defaultCacheSize
}

if cfg.LabelsMap != nil {
if cfg.LabelsMap.RequestHeaderName == "" || len(cfg.LabelsMap.Labels) == 0 {
cfg.LabelsMap = nil
}
}

c := &Canary{
name: name,
next: next,
Expand All @@ -80,6 +87,7 @@ func New(ctx context.Context, next http.Handler, cfg dynamic.Canary, name string
addRequestID: cfg.AddRequestID,
canaryResponseHeader: cfg.CanaryResponseHeader,
sticky: cfg.Sticky,
labelsMap: cfg.LabelsMap,
}

if cfg.Sticky != nil {
Expand Down Expand Up @@ -147,15 +155,26 @@ func (c *Canary) processCanary(rw http.ResponseWriter, req *http.Request) {
} else {
// load user's labels and update to header when work as public gateway.
info.fromHeader(req.Header, false)

// try load labels from cookie when not exists in request X-Canary header.
if info.label == "" {
if cookie, _ := req.Cookie(headerXCanary); cookie != nil && cookie.Value != "" {
info.feed(strings.Split(cookie.Value, ","), false)
}
}

// try load labels from config with header when not exists.
if info.label == "" && c.labelsMap != nil {
key := req.Header.Get(c.labelsMap.RequestHeaderName)
if vals := c.labelsMap.Labels[key]; vals != "" {
info.feed(strings.Split(vals, ","), false)
}
}

info.product = c.product
info.uid = extractUserID(req, c.uidCookies)

// anonymous user
if info.uid == "" && c.sticky != nil {
addr := req.Header.Get("X-Real-Ip")
if addr == "" {
Expand All @@ -168,6 +187,7 @@ func (c *Canary) processCanary(rw http.ResponseWriter, req *http.Request) {
c.addSticky(info.uid, rw)
}

// try load labels from server
if info.label == "" && info.uid != "" {
labels := c.ls.MustLoadLabels(req.Context(), info.uid, req.Header.Get(headerXRequestID))
for _, l := range labels {
Expand Down

0 comments on commit 9e24f89

Please sign in to comment.