mirror of
https://github.com/hanzoai/oxy.git
synced 2026-09-30 23:42:31 +00:00
87 lines
2.2 KiB
Go
87 lines
2.2 KiB
Go
package roundrobin
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/vulcand/oxy/v2/roundrobin/stickycookie"
|
|
)
|
|
|
|
// CookieOptions has all the options one would like to set on the affinity cookie.
|
|
type CookieOptions struct {
|
|
HTTPOnly bool
|
|
Secure bool
|
|
|
|
Path string
|
|
Domain string
|
|
Expires time.Time
|
|
|
|
MaxAge int
|
|
SameSite http.SameSite
|
|
}
|
|
|
|
// StickySession is a mixin for load balancers that implements layer 7 (http cookie) session affinity.
|
|
type StickySession struct {
|
|
cookieName string
|
|
cookieValue stickycookie.CookieValue
|
|
options CookieOptions
|
|
}
|
|
|
|
// NewStickySession creates a new StickySession.
|
|
func NewStickySession(cookieName string) *StickySession {
|
|
return &StickySession{cookieName: cookieName, cookieValue: &stickycookie.RawValue{}}
|
|
}
|
|
|
|
// NewStickySessionWithOptions creates a new StickySession whilst allowing for options to
|
|
// shape its affinity cookie such as "httpOnly" or "secure".
|
|
func NewStickySessionWithOptions(cookieName string, options CookieOptions) *StickySession {
|
|
return &StickySession{cookieName: cookieName, options: options, cookieValue: &stickycookie.RawValue{}}
|
|
}
|
|
|
|
// SetCookieValue set the CookieValue for the StickySession.
|
|
func (s *StickySession) SetCookieValue(value stickycookie.CookieValue) *StickySession {
|
|
s.cookieValue = value
|
|
return s
|
|
}
|
|
|
|
// 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) {
|
|
cookie, err := req.Cookie(s.cookieName)
|
|
if err != nil {
|
|
if errors.Is(err, http.ErrNoCookie) {
|
|
return nil, false, nil
|
|
}
|
|
|
|
return nil, false, err
|
|
}
|
|
|
|
server, err := s.cookieValue.FindURL(cookie.Value, servers)
|
|
|
|
return server, server != nil, err
|
|
}
|
|
|
|
// StickBackend creates and sets the cookie.
|
|
func (s *StickySession) StickBackend(backend *url.URL, w http.ResponseWriter) {
|
|
opt := s.options
|
|
|
|
cp := "/"
|
|
if opt.Path != "" {
|
|
cp = opt.Path
|
|
}
|
|
|
|
cookie := &http.Cookie{
|
|
Name: s.cookieName,
|
|
Value: s.cookieValue.Get(backend),
|
|
Path: cp,
|
|
Domain: opt.Domain,
|
|
Expires: opt.Expires,
|
|
MaxAge: opt.MaxAge,
|
|
Secure: opt.Secure,
|
|
HttpOnly: opt.HTTPOnly,
|
|
SameSite: opt.SameSite,
|
|
}
|
|
http.SetCookie(w, cookie)
|
|
}
|