Documentation
¶
Index ¶
- Variables
- func BidirectionalCopy(client, upstream net.Conn) error
- func ClearTransportCache()
- func CreateProxyTransport(p *models.Proxy) (*http.Transport, error)
- func GetOrCreateTransport(p *models.Proxy) (*http.Transport, error)
- func InvalidateTransport(p *models.Proxy)
- type AuthMiddleware
- func (m *AuthMiddleware) HandleConnect(req *http.Request) (*http.Request, *http.Response)
- func (m *AuthMiddleware) HandleRequest(req *http.Request) (*http.Request, *http.Response)
- func (m *AuthMiddleware) IsEnabled() bool
- func (m *AuthMiddleware) UpdateSettings(settings models.AuthenticationSettings)
- type BaseSelector
- type HealthChecker
- func (h *HealthChecker) CheckAllProxies(ctx context.Context) ([]models.ProxyTestResult, error)
- func (h *HealthChecker) CheckAllProxiesWithProgress(ctx context.Context, onProgress func(checked, active, failed int), ...) ([]models.ProxyTestResult, error)
- func (h *HealthChecker) CheckProxy(ctx context.Context, proxy *models.Proxy, immediate bool) (*models.ProxyTestResult, error)
- func (h *HealthChecker) StartPeriodicHealthCheck(ctx context.Context, interval time.Duration)
- type LeastConnectionsSelector
- type PoolChain
- type PoolSelector
- type ProxySelector
- type RandomSelector
- type RateLimitMiddleware
- func (m *RateLimitMiddleware) CleanupLimiters()
- func (m *RateLimitMiddleware) HandleConnect(req *http.Request) (*http.Request, *http.Response)
- func (m *RateLimitMiddleware) HandleRequest(req *http.Request) (*http.Request, *http.Response)
- func (m *RateLimitMiddleware) UpdateSettings(settings models.RateLimitSettings)
- type RequestRecord
- type RoundRobinSelector
- type Server
- type TimeBasedSelector
- type UpstreamProxyHandler
- type UsageTracker
- func (t *UsageTracker) GetRecentRequests(ctx context.Context, proxyID int, limit int) ([]RequestRecord, error)
- func (t *UsageTracker) RecordHealthCheck(ctx context.Context, proxyID int, success bool, responseTime int, ...) error
- func (t *UsageTracker) RecordManualTestResult(ctx context.Context, proxyID int, success bool, errorMsg string) error
- func (t *UsageTracker) RecordRequest(ctx context.Context, record RequestRecord) error
- func (t *UsageTracker) StartBatchWriter(log *logger.Logger)
- func (t *UsageTracker) Stop()
- func (t *UsageTracker) UpdateProxyStatus(ctx context.Context, proxyID int, status string) error
- type UserAuthMiddleware
Constants ¶
This section is empty.
Variables ¶
var UserChainContextKey = userChainKey{}
UserChainContextKey is exported for use in the handler.
Functions ¶
func BidirectionalCopy ¶
BidirectionalCopy copies data between client and upstream in both directions concurrently. It returns when either direction encounters an error or EOF. On Linux with raw TCP sockets, it attempts splice(2) for zero-copy transfer before falling back to io.Copy.
func ClearTransportCache ¶
func ClearTransportCache()
ClearTransportCache drops all cached transports.
func CreateProxyTransport ¶
CreateProxyTransport creates an HTTP transport configured for the given proxy This is shared between proxy handler and health checker
func GetOrCreateTransport ¶
GetOrCreateTransport returns a cached transport for the given proxy, or creates and caches a new one.
func InvalidateTransport ¶
InvalidateTransport removes any cached transport(s) for the given proxy, regardless of credentials/version. Callers should invoke this when a proxy is updated or deleted so the next request rebuilds with fresh settings.
Types ¶
type AuthMiddleware ¶
type AuthMiddleware struct {
// contains filtered or unexported fields
}
AuthMiddleware handles proxy authentication
func NewAuthMiddleware ¶
func NewAuthMiddleware(settings models.AuthenticationSettings) *AuthMiddleware
NewAuthMiddleware creates a new authentication middleware
func (*AuthMiddleware) HandleConnect ¶
HandleConnect validates proxy authentication for HTTPS CONNECT requests
func (*AuthMiddleware) HandleRequest ¶
HandleRequest validates proxy authentication for HTTP requests
func (*AuthMiddleware) IsEnabled ¶
func (m *AuthMiddleware) IsEnabled() bool
IsEnabled reports whether legacy single-user auth is currently enforcing.
func (*AuthMiddleware) UpdateSettings ¶
func (m *AuthMiddleware) UpdateSettings(settings models.AuthenticationSettings)
UpdateSettings updates the authentication settings
type BaseSelector ¶
type BaseSelector struct {
// contains filtered or unexported fields
}
BaseSelector contains common fields for all selectors
type HealthChecker ¶
type HealthChecker struct {
// contains filtered or unexported fields
}
HealthChecker manages proxy health checking
func NewHealthChecker ¶
func NewHealthChecker( proxyRepo *repository.ProxyRepository, settingsRepo *repository.SettingsRepository, tracker *UsageTracker, log *logger.Logger, ) *HealthChecker
NewHealthChecker creates a new health checker
func (*HealthChecker) CheckAllProxies ¶
func (h *HealthChecker) CheckAllProxies(ctx context.Context) ([]models.ProxyTestResult, error)
CheckAllProxies tests all proxies concurrently with periodic (non-immediate) status accounting.
func (*HealthChecker) CheckAllProxiesWithProgress ¶
func (h *HealthChecker) CheckAllProxiesWithProgress( ctx context.Context, onProgress func(checked, active, failed int), immediate bool, ) ([]models.ProxyTestResult, error)
CheckAllProxiesWithProgress tests all proxies concurrently, calling onProgress(checked, active, failed) after each proxy is checked (nil-safe). immediate=true applies each result to the proxy status right away (user-initiated); false keeps the consecutive-failure accounting.
func (*HealthChecker) CheckProxy ¶
func (h *HealthChecker) CheckProxy(ctx context.Context, proxy *models.Proxy, immediate bool) (*models.ProxyTestResult, error)
CheckProxy tests a single proxy. When immediate is true (user-initiated manual test) the result is applied to the proxy status right away; when false (periodic/background) the consecutive-failure accounting applies.
func (*HealthChecker) StartPeriodicHealthCheck ¶
func (h *HealthChecker) StartPeriodicHealthCheck(ctx context.Context, interval time.Duration)
StartPeriodicHealthCheck starts a background health check routine
type LeastConnectionsSelector ¶
type LeastConnectionsSelector struct {
*BaseSelector
// contains filtered or unexported fields
}
LeastConnectionsSelector selects the proxy with the lowest usage count
func NewLeastConnectionsSelector ¶
func NewLeastConnectionsSelector(repo *repository.ProxyRepository, settings *models.RotationSettings) *LeastConnectionsSelector
NewLeastConnectionsSelector creates a new least connections selector
type PoolChain ¶
type PoolChain struct {
// contains filtered or unexported fields
}
PoolChain holds an ordered list of pool selectors for a user: index 0 = main pool, index 1..N = fallback pools. It refreshes pool selectors periodically and provides the high-level SendWithRetry / ConnectWithRetry methods used by the proxy handler.
func NewPoolChain ¶
func NewPoolChain(db *database.DB, pools []models.ProxyPool, maxRetry int, log *logger.Logger) *PoolChain
NewPoolChain builds a PoolChain from an ordered list of ProxyPool objects.
func (*PoolChain) ConnectWithRetry ¶
func (c *PoolChain) ConnectWithRetry( host string, ctx context.Context, rotationSettings *models.RotationSettings, log *logger.Logger, ) (net.Conn, int, error)
ConnectWithRetry establishes a TCP tunnel (HTTPS CONNECT) through the chain.
func (*PoolChain) SendWithRetry ¶
func (c *PoolChain) SendWithRetry( req *http.Request, ctx context.Context, rotationSettings *models.RotationSettings, log *logger.Logger, ) (*http.Response, int, error)
SendWithRetry attempts to forward an HTTP request through the chain. On each attempt it picks the next fresh proxy. If a pool has no active proxies it moves to the next pool automatically.
type PoolSelector ¶
type PoolSelector struct {
// contains filtered or unexported fields
}
PoolSelector selects a proxy from a specific pool using the pool's rotation strategy. It keeps in-memory state (round-robin index, stick counters) per pool instance.
func NewPoolSelector ¶
func NewPoolSelector(db *database.DB, pool models.ProxyPool) *PoolSelector
NewPoolSelector creates a PoolSelector for the given pool.
func (*PoolSelector) HasActive ¶
func (ps *PoolSelector) HasActive() bool
HasActive returns true if the pool currently has at least one active/idle proxy.
func (*PoolSelector) Refresh ¶
func (ps *PoolSelector) Refresh(ctx context.Context) error
Refresh reloads only active/idle proxies that belong to this pool.
func (*PoolSelector) RemoveProxy ¶
func (ps *PoolSelector) RemoveProxy(proxyID int)
RemoveProxy removes a specific proxy from the in-memory list (called after failure).
type ProxySelector ¶
type ProxySelector interface {
Select(ctx context.Context) (*models.Proxy, error)
Refresh(ctx context.Context) error
}
ProxySelector defines the interface for proxy selection strategies
func NewProxySelector ¶
func NewProxySelector(repo *repository.ProxyRepository, settings *models.RotationSettings) (ProxySelector, error)
NewProxySelector creates a proxy selector based on settings
type RandomSelector ¶
type RandomSelector struct {
*BaseSelector
}
RandomSelector selects a random proxy
func NewRandomSelector ¶
func NewRandomSelector(repo *repository.ProxyRepository, settings *models.RotationSettings) *RandomSelector
NewRandomSelector creates a new random selector
type RateLimitMiddleware ¶
type RateLimitMiddleware struct {
// contains filtered or unexported fields
}
RateLimitMiddleware handles per-IP rate limiting
func NewRateLimitMiddleware ¶
func NewRateLimitMiddleware(settings models.RateLimitSettings) *RateLimitMiddleware
NewRateLimitMiddleware creates a new rate limiting middleware
func (*RateLimitMiddleware) CleanupLimiters ¶
func (m *RateLimitMiddleware) CleanupLimiters()
CleanupLimiters removes limiters for IPs that haven't been seen recently Should be called periodically to prevent memory leaks
func (*RateLimitMiddleware) HandleConnect ¶
HandleConnect validates rate limits for HTTPS CONNECT requests
func (*RateLimitMiddleware) HandleRequest ¶
HandleRequest validates rate limits for HTTP requests
func (*RateLimitMiddleware) UpdateSettings ¶
func (m *RateLimitMiddleware) UpdateSettings(settings models.RateLimitSettings)
UpdateSettings updates the rate limit settings
type RequestRecord ¶
type RequestRecord struct {
ProxyID int
ProxyAddress string
RequestedURL string
Method string
Success bool
ResponseTime int // milliseconds
StatusCode int
ErrorMessage string
Timestamp time.Time
}
RequestRecord represents a single proxy request
type RoundRobinSelector ¶
type RoundRobinSelector struct {
*BaseSelector
// contains filtered or unexported fields
}
RoundRobinSelector selects proxies in sequential order
func NewRoundRobinSelector ¶
func NewRoundRobinSelector(repo *repository.ProxyRepository, settings *models.RotationSettings) *RoundRobinSelector
NewRoundRobinSelector creates a new round-robin selector
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server represents the proxy server
func New ¶
func New( port int, log *logger.Logger, db *database.DB, proxyRepo *repository.ProxyRepository, poolRepo *repository.PoolRepository, userRepo *repository.UserRepository, settingsRepo *repository.SettingsRepository, ) (*Server, error)
New creates a new proxy server instance
func (*Server) ReloadSettings ¶
ReloadSettings reloads settings from database and updates components
type TimeBasedSelector ¶
type TimeBasedSelector struct {
*BaseSelector
// contains filtered or unexported fields
}
TimeBasedSelector selects proxy based on time intervals
func NewTimeBasedSelector ¶
func NewTimeBasedSelector(repo *repository.ProxyRepository, settings *models.RotationSettings, intervalSeconds int) *TimeBasedSelector
NewTimeBasedSelector creates a new time-based selector
type UpstreamProxyHandler ¶
type UpstreamProxyHandler struct {
// contains filtered or unexported fields
}
UpstreamProxyHandler handles requests with upstream proxy rotation
func NewUpstreamProxyHandler ¶
func NewUpstreamProxyHandler( selector ProxySelector, tracker *UsageTracker, settings *models.RotationSettings, log *logger.Logger, ) *UpstreamProxyHandler
NewUpstreamProxyHandler creates a new upstream proxy handler
func (*UpstreamProxyHandler) HandleConnectRequest ¶
func (h *UpstreamProxyHandler) HandleConnectRequest(w http.ResponseWriter, r *http.Request)
HandleConnectRequest handles HTTPS CONNECT requests. It hijacks the client connection, establishes an upstream tunnel, and copies data bidirectionally using splice(2) on Linux.
func (*UpstreamProxyHandler) HandleHTTPRequest ¶
func (h *UpstreamProxyHandler) HandleHTTPRequest(w http.ResponseWriter, r *http.Request)
HandleHTTPRequest handles HTTP requests (non-CONNECT) with upstream proxy rotation. It writes the proxied response directly to w.
type UsageTracker ¶
type UsageTracker struct {
// contains filtered or unexported fields
}
UsageTracker tracks proxy usage and updates statistics.
On the request hot path, per-request synchronous DB writes (one INSERT + one UPDATE each) are the dominant scaling cost. When a batch writer is started (StartBatchWriter), RecordRequest instead enqueues onto a buffered channel and a single worker coalesces records: bulk-inserting proxy_requests via CopyFrom and folding per-proxy stat deltas into one UPDATE per proxy per flush window. This turns O(requests) round-trips into O(distinct proxies / second).
func NewUsageTracker ¶
func NewUsageTracker(repo *repository.ProxyRepository) *UsageTracker
NewUsageTracker creates a new usage tracker. It writes synchronously until StartBatchWriter is called.
func (*UsageTracker) GetRecentRequests ¶
func (t *UsageTracker) GetRecentRequests(ctx context.Context, proxyID int, limit int) ([]RequestRecord, error)
GetRecentRequests retrieves recent requests for a proxy
func (*UsageTracker) RecordHealthCheck ¶
func (t *UsageTracker) RecordHealthCheck(ctx context.Context, proxyID int, success bool, responseTime int, errorMsg string) error
RecordHealthCheck records a health check result
func (*UsageTracker) RecordManualTestResult ¶
func (t *UsageTracker) RecordManualTestResult(ctx context.Context, proxyID int, success bool, errorMsg string) error
RecordManualTestResult persists the result of an explicit manual proxy test. Status is applied immediately: success -> 'active', failure -> 'failed'. The consecutive-failure counter is kept consistent: reset on success, incremented on failure.
func (*UsageTracker) RecordRequest ¶
func (t *UsageTracker) RecordRequest(ctx context.Context, record RequestRecord) error
RecordRequest records a proxy request. With the batch writer running it is a non-blocking enqueue (dropping on overflow); otherwise it writes synchronously.
func (*UsageTracker) StartBatchWriter ¶
func (t *UsageTracker) StartBatchWriter(log *logger.Logger)
StartBatchWriter enables asynchronous batched stat writes. Idempotent.
func (*UsageTracker) Stop ¶
func (t *UsageTracker) Stop()
Stop drains and flushes any buffered records and stops the batch writer.
func (*UsageTracker) UpdateProxyStatus ¶
UpdateProxyStatus updates only the status of a proxy
type UserAuthMiddleware ¶
type UserAuthMiddleware struct {
// contains filtered or unexported fields
}
UserAuthMiddleware resolves Proxy-Authorization credentials against proxy_users. When a matching enabled user is found it attaches a *PoolChain to the request context. If user-based auth is not configured (no proxy_users) and the legacy single-user auth is enabled, it falls through to the original AuthMiddleware behaviour.
func NewUserAuthMiddleware ¶
func NewUserAuthMiddleware( userRepo *repository.UserRepository, poolRepo *repository.PoolRepository, db *database.DB, legacy *AuthMiddleware, rotSettings *models.RotationSettings, log *logger.Logger, ) *UserAuthMiddleware
NewUserAuthMiddleware creates the middleware.
func (*UserAuthMiddleware) HandleConnect ¶
HandleConnect is the same but for HTTPS CONNECT.
func (*UserAuthMiddleware) HandleRequest ¶
HandleRequest is called for every HTTP proxy request. It reads Proxy-Authorization, looks up the user, builds a PoolChain and stores it in the request context so the handler can use it.
func (*UserAuthMiddleware) InvalidateUser ¶
func (m *UserAuthMiddleware) InvalidateUser(username string)
InvalidateUser removes a user's cached chain (call after user is updated/deleted).