traefik/vendor/github.com/vulcand/oxy/roundrobin/stickysessions.go

57 lines
1.3 KiB
Go
Raw Normal View History

2017-02-07 21:33:23 +00:00
// package stickysession is a mixin for load balancers that implements layer 7 (http cookie) session affinity
package roundrobin
import (
"net/http"
"net/url"
)
type StickySession struct {
2017-11-22 17:20:03 +00:00
cookieName string
2017-02-07 21:33:23 +00:00
}
2017-11-22 17:20:03 +00:00
func NewStickySession(cookieName string) *StickySession {
return &StickySession{cookieName}
2017-02-07 21:33:23 +00:00
}
// GetBackend returns the backend URL stored in the sticky cookie, iff the backend is still in the valid list of servers.
func (s *StickySession) GetBackend(req *http.Request, servers []*url.URL) (*url.URL, bool, error) {
2017-11-22 17:20:03 +00:00
cookie, err := req.Cookie(s.cookieName)
2017-02-07 21:33:23 +00:00
switch err {
case nil:
case http.ErrNoCookie:
return nil, false, nil
default:
return nil, false, err
}
2017-11-22 17:20:03 +00:00
serverURL, err := url.Parse(cookie.Value)
2017-02-07 21:33:23 +00:00
if err != nil {
return nil, false, err
}
2017-11-22 17:20:03 +00:00
if s.isBackendAlive(serverURL, servers) {
return serverURL, true, nil
2017-02-07 21:33:23 +00:00
} else {
return nil, false, nil
}
}
func (s *StickySession) StickBackend(backend *url.URL, w *http.ResponseWriter) {
2017-11-22 17:20:03 +00:00
cookie := &http.Cookie{Name: s.cookieName, Value: backend.String(), Path: "/"}
http.SetCookie(*w, cookie)
2017-02-07 21:33:23 +00:00
}
func (s *StickySession) isBackendAlive(needle *url.URL, haystack []*url.URL) bool {
if len(haystack) == 0 {
return false
}
2017-11-22 17:20:03 +00:00
for _, serverURL := range haystack {
if sameURL(needle, serverURL) {
2017-02-07 21:33:23 +00:00
return true
}
}
return false
}