mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 15:26:40 +00:00
167 lines
3.7 KiB
Go
167 lines
3.7 KiB
Go
package proxy
|
|
|
|
import (
|
|
"context"
|
|
"net/netip"
|
|
"sync"
|
|
|
|
"github.com/netbirdio/netbird/proxy/internal/types"
|
|
)
|
|
|
|
type requestContextKey string
|
|
|
|
const (
|
|
capturedDataKey requestContextKey = "capturedData"
|
|
)
|
|
|
|
// ResponseOrigin indicates where a response was generated.
|
|
type ResponseOrigin int
|
|
|
|
const (
|
|
// OriginBackend means the response came from the backend service.
|
|
OriginBackend ResponseOrigin = iota
|
|
// OriginNoRoute means the proxy had no matching host or path.
|
|
OriginNoRoute
|
|
// OriginProxyError means the proxy failed to reach the backend.
|
|
OriginProxyError
|
|
// OriginAuth means the proxy intercepted the request for authentication.
|
|
OriginAuth
|
|
)
|
|
|
|
func (o ResponseOrigin) String() string {
|
|
switch o {
|
|
case OriginNoRoute:
|
|
return "no_route"
|
|
case OriginProxyError:
|
|
return "proxy_error"
|
|
case OriginAuth:
|
|
return "auth"
|
|
default:
|
|
return "backend"
|
|
}
|
|
}
|
|
|
|
// CapturedData is a mutable struct that allows downstream handlers
|
|
// to pass data back up the middleware chain.
|
|
type CapturedData struct {
|
|
mu sync.RWMutex
|
|
requestID string
|
|
serviceID types.ServiceID
|
|
accountID types.AccountID
|
|
origin ResponseOrigin
|
|
clientIP netip.Addr
|
|
userID string
|
|
authMethod string
|
|
}
|
|
|
|
// NewCapturedData creates a CapturedData with the given request ID.
|
|
func NewCapturedData(requestID string) *CapturedData {
|
|
return &CapturedData{requestID: requestID}
|
|
}
|
|
|
|
// GetRequestID returns the request ID.
|
|
func (c *CapturedData) GetRequestID() string {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.requestID
|
|
}
|
|
|
|
// SetServiceID sets the service ID.
|
|
func (c *CapturedData) SetServiceID(serviceID types.ServiceID) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.serviceID = serviceID
|
|
}
|
|
|
|
// GetServiceID returns the service ID.
|
|
func (c *CapturedData) GetServiceID() types.ServiceID {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.serviceID
|
|
}
|
|
|
|
// SetAccountID sets the account ID.
|
|
func (c *CapturedData) SetAccountID(accountID types.AccountID) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.accountID = accountID
|
|
}
|
|
|
|
// GetAccountID returns the account ID.
|
|
func (c *CapturedData) GetAccountID() types.AccountID {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.accountID
|
|
}
|
|
|
|
// SetOrigin sets the response origin.
|
|
func (c *CapturedData) SetOrigin(origin ResponseOrigin) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.origin = origin
|
|
}
|
|
|
|
// GetOrigin returns the response origin.
|
|
func (c *CapturedData) GetOrigin() ResponseOrigin {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.origin
|
|
}
|
|
|
|
// SetClientIP sets the resolved client IP.
|
|
func (c *CapturedData) SetClientIP(ip netip.Addr) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.clientIP = ip
|
|
}
|
|
|
|
// GetClientIP returns the resolved client IP.
|
|
func (c *CapturedData) GetClientIP() netip.Addr {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.clientIP
|
|
}
|
|
|
|
// SetUserID sets the authenticated user ID.
|
|
func (c *CapturedData) SetUserID(userID string) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.userID = userID
|
|
}
|
|
|
|
// GetUserID returns the authenticated user ID.
|
|
func (c *CapturedData) GetUserID() string {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.userID
|
|
}
|
|
|
|
// SetAuthMethod sets the authentication method used.
|
|
func (c *CapturedData) SetAuthMethod(method string) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.authMethod = method
|
|
}
|
|
|
|
// GetAuthMethod returns the authentication method used.
|
|
func (c *CapturedData) GetAuthMethod() string {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.authMethod
|
|
}
|
|
|
|
// WithCapturedData adds a CapturedData struct to the context.
|
|
func WithCapturedData(ctx context.Context, data *CapturedData) context.Context {
|
|
return context.WithValue(ctx, capturedDataKey, data)
|
|
}
|
|
|
|
// CapturedDataFromContext retrieves the CapturedData from context.
|
|
func CapturedDataFromContext(ctx context.Context) *CapturedData {
|
|
v := ctx.Value(capturedDataKey)
|
|
data, ok := v.(*CapturedData)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return data
|
|
}
|