mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-18 23:44:40 +01:00
52 lines
1.3 KiB
Go
52 lines
1.3 KiB
Go
package loadbalancer
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"github.com/bytedance/gopkg/util/xxhash3"
|
|
"github.com/yusing/godoxy/internal/types"
|
|
)
|
|
|
|
func hashServerKey(key string) string {
|
|
h := xxhash3.HashString(key)
|
|
as8bytes := *(*[8]byte)(unsafe.Pointer(&h))
|
|
return hex.EncodeToString(as8bytes[:])
|
|
}
|
|
|
|
// getStickyServer extracts the sticky session cookie and returns the corresponding server
|
|
func getStickyServer(r *http.Request, srvs []types.LoadBalancerServer) types.LoadBalancerServer {
|
|
cookie, err := r.Cookie("godoxy_lb_sticky")
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
serverKeyHash := cookie.Value
|
|
for _, srv := range srvs {
|
|
if hashServerKey(srv.Key()) == serverKeyHash {
|
|
return srv
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// setStickyCookie sets a cookie to maintain sticky session with a specific server
|
|
func setStickyCookie(rw http.ResponseWriter, r *http.Request, srv types.LoadBalancerServer, maxAge time.Duration) {
|
|
http.SetCookie(rw, &http.Cookie{
|
|
Name: "godoxy_lb_sticky",
|
|
Value: hashServerKey(srv.Key()),
|
|
Path: "/",
|
|
MaxAge: int(maxAge.Seconds()),
|
|
SameSite: http.SameSiteLaxMode,
|
|
HttpOnly: true,
|
|
Secure: isSecure(r),
|
|
})
|
|
}
|
|
|
|
func isSecure(r *http.Request) bool {
|
|
return r.TLS != nil || strings.EqualFold(r.Header.Get("X-Forwarded-Proto"), "https")
|
|
}
|