plugin

package
v0.31.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package plugin implements external plugin process management.

Plugins are external executables that communicate with prox over stdin/stdout using line-delimited JSON messages for lifecycle events, and over a Unix socket using length-prefixed msgpack frames for request-response hooks (on_request, on_response, on_connect).

Index

Constants

View Source
const (
	MethodConfigure  = "configure"
	MethodSetTargets = "set_targets"
	MethodSetSpeed   = "set_speed"
	MethodReady      = "ready"
	MethodLog        = "log"
)

Method constants for the stdin/stdout JSON protocol.

View Source
const (
	HookOnRequest    = "on_request"
	HookOnResponse   = "on_response"
	HookOnConnect    = "on_connect"
	HookOnDisconnect = "on_disconnect"
)

Hook names advertised by plugins.

Variables

This section is empty.

Functions

func BuildPlugins

func BuildPlugins(paths []string) error

BuildPlugins compiles all plugin sources into binaries. Each path can be a .go file, a directory containing Go source, or a pre-compiled binary (skipped). Returns the first error encountered.

func MarshalEnvelope

func MarshalEnvelope(hook HookType, data interface{}) ([]byte, error)

MarshalEnvelope creates a framed envelope for the given hook type and data. Uses a pooled buffer to avoid intermediate allocations.

Types

type AuthorizeResult

type AuthorizeResult struct {
	Allow       bool              `msgpack:"ok"`
	Drop        bool              `msgpack:"dr,omitempty"`
	Fallback    bool              `msgpack:"fb,omitempty"`
	Status      int               `msgpack:"s,omitempty"`
	Body        string            `msgpack:"b,omitempty"`
	Headers     map[string]string `msgpack:"h,omitempty"`
	SpeedLimit  *SpeedLimit       `msgpack:"sp,omitempty"`
	CleanQuery  bool              `msgpack:"cq,omitempty"`
	RewritePath string            `msgpack:"rp,omitempty"`
}

AuthorizeResult is the plugin's verdict for an on_request hook.

type Binding

type Binding struct {
	Name     string // human-readable alias from config
	RouteID  string
	Plugin   string // absolute path to plugin binary
	Match    *MatchInfo
	Balancer balancer.Balancer
	Timeout  time.Duration // per-request plugin call timeout
}

Binding associates a route with a plugin process and its balancer.

type Caller

type Caller struct {
	// contains filtered or unexported fields
}

Caller manages a connection pool to a plugin's Unix socket. Each connection handles one request at a time — prox grabs a connection, writes a request frame, reads the response, and returns the connection to the pool. This gives natural concurrency without ID correlation or multiplexing.

func NewCaller

func NewCaller(socketPath string, poolSize int, timeout time.Duration) *Caller

NewCaller creates a Caller that connects to the given Unix socket.

func (*Caller) CallConnect

func (c *Caller) CallConnect(ctx context.Context, conn *ConnInfo) (*ConnResult, error)

CallConnect sends an on_connect hook and returns the plugin's verdict.

func (*Caller) CallRequest

func (c *Caller) CallRequest(ctx context.Context, req *RequestInfo) (*AuthorizeResult, error)

CallRequest sends an on_request hook and returns the plugin's verdict.

func (*Caller) CallResponse

func (c *Caller) CallResponse(ctx context.Context, req *RequestInfo, resp *UpstreamResponseInfo) (*ResponseModResult, error)

CallResponse sends an on_response hook and returns response modifications.

func (*Caller) Close

func (c *Caller) Close()

Close drains the connection pool and closes all connections.

func (*Caller) Fire

func (c *Caller) Fire(frame []byte) error

Fire sends a frame without waiting for a response (fire-and-forget). Used for disconnect notifications. The connection is returned to the pool after writing; the plugin's read loop simply advances to the next frame.

type ConfigureParams

type ConfigureParams struct {
	RouteID string     `json:"route_id"`
	Match   *MatchInfo `json:"match,omitempty"`
}

ConfigureParams is sent to the plugin on startup and after reload.

type ConnInfo

type ConnInfo struct {
	RouteID     string `msgpack:"r"`
	Domain      string `msgpack:"d"`
	RemoteAddr  string `msgpack:"a"`
	MatchDomain string `msgpack:"md,omitempty"`
	MatchGlob   string `msgpack:"mg,omitempty"`
}

ConnInfo carries L4 connection context for on_connect hooks.

type ConnResult

type ConnResult struct {
	Allow bool `msgpack:"ok"`
}

ConnResult is the plugin's verdict for an on_connect hook.

type DisconnectInfo

type DisconnectInfo struct {
	RouteID    string `msgpack:"r"`
	Target     string `msgpack:"tg,omitempty"`
	RemoteAddr string `msgpack:"a"`
	BytesRx    int64  `msgpack:"rx"`
	BytesTx    int64  `msgpack:"tx"`
	DurationMs int64  `msgpack:"ms"`
}

DisconnectInfo carries statistics for the on_disconnect hook.

type Envelope

type Envelope struct {
	Hook HookType `msgpack:"t"`
	Data []byte   `msgpack:"d"`
}

Envelope wraps all socket messages with a type discriminator.

type HookType

type HookType byte

HookType identifies the hook being invoked over the socket.

const (
	HookTypeRequest    HookType = 1
	HookTypeResponse   HookType = 2
	HookTypeConnect    HookType = 3
	HookTypeDisconnect HookType = 4
)

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager supervises plugin processes and routes push messages to balancers. It also provides the hook call API (OnRequest, OnResponse, OnConnect, OnDisconnect) for the HTTP handler and L4 dispatcher.

func NewManager

func NewManager() *Manager

NewManager creates a plugin manager. Call Start() to spawn processes.

func (*Manager) Configure

func (m *Manager) Configure(bindings []*Binding, routes map[string]*RouteInfo)

Configure sets the current route-to-plugin bindings and global route info. Call Start() after Configure() to spawn processes.

func (*Manager) GetSpeedLimit

func (m *Manager) GetSpeedLimit(routeID string) SpeedEntry

GetSpeedLimit returns the plugin-pushed speed limit for a route. Lock-free: reads from the atomic speed index.

func (*Manager) GroupBuckets

func (m *Manager) GroupBuckets() *throttle.GroupRegistry

GroupBuckets returns the shared group speed bucket registry.

func (*Manager) HasHook

func (m *Manager) HasHook(routeID string, hook string) bool

HasHook returns true if any plugin bound to the route supports the given hook. Lock-free: reads from the atomic hook index.

func (*Manager) OnConnect

func (m *Manager) OnConnect(ctx context.Context, routeID string, conn *ConnInfo) (*ConnResult, error)

OnConnect calls the on_connect hook for all plugins bound to the route. Sequential execution, short-circuit on first deny.

func (*Manager) OnDisconnect

func (m *Manager) OnDisconnect(routeID string, info *DisconnectInfo)

OnDisconnect fires a disconnect notification to all plugins bound to the route. Non-blocking: marshals the frame and sends to a buffered channel. Dropped silently if the channel is full (fire-and-forget).

func (*Manager) OnRequest

func (m *Manager) OnRequest(ctx context.Context, routeID string, req *RequestInfo) (*AuthorizeResult, error)

OnRequest calls the on_request hook for all plugins bound to the route. Sequential execution, short-circuit on first deny.

func (*Manager) OnResponse

func (m *Manager) OnResponse(ctx context.Context, routeID string, req *RequestInfo, resp *UpstreamResponseInfo) (*ResponseModResult, error)

OnResponse calls the on_response hook for all plugins bound to the route.

func (*Manager) Reconfigure

func (m *Manager) Reconfigure(bindings []*Binding, routes map[string]*RouteInfo)

Reconfigure updates bindings and reconfigures running plugins. New plugins are started, removed plugins are stopped.

func (*Manager) Start

func (m *Manager) Start(ctx context.Context) error

Start spawns all plugin processes and begins processing pushes.

func (*Manager) Stop

func (m *Manager) Stop()

Stop gracefully terminates all plugin processes.

type MatchInfo

type MatchInfo struct {
	Domain string `json:"domain,omitempty"`
	Path   string `json:"path,omitempty"`
}

MatchInfo provides the route's match criteria to the plugin.

type Process

type Process struct {
	// contains filtered or unexported fields
}

Process wraps a single plugin subprocess.

func (*Process) Done

func (p *Process) Done() <-chan struct{}

Done returns a channel that closes when the process exits.

func (*Process) Pushes

func (p *Process) Pushes() <-chan Push

Pushes returns the channel of incoming push messages.

func (*Process) Send

func (p *Process) Send(req Request) error

Send writes a JSON request to the plugin's stdin.

func (*Process) Stop

func (p *Process) Stop()

Stop terminates the plugin process gracefully.

type Push

type Push struct {
	Method string     `json:"method"`
	Params PushParams `json:"params"`
}

Push is a message sent from a plugin to prox via stdout.

type PushParams

type PushParams struct {
	RouteID string              `json:"route_id,omitempty"`
	Action  string              `json:"action,omitempty"` // target routes by action name
	Targets []string            `json:"targets,omitempty"`
	Groups  map[string][]string `json:"groups,omitempty"`

	// Ready-specific fields (only when Method == "ready").
	Socket string   `json:"socket,omitempty"`
	Hooks  []string `json:"hooks,omitempty"`

	DownloadMbps float64 `json:"download_mbps,omitempty"`
	UploadMbps   float64 `json:"upload_mbps,omitempty"`
	GroupKey     string  `json:"group_key,omitempty"`

	// Log-specific fields (only when Method == "log").
	Level   string `json:"level,omitempty"`
	Message string `json:"message,omitempty"`
	Args    []any  `json:"args,omitempty"`
}

PushParams carries the data for a push message.

type Request

type Request struct {
	Method string      `json:"method"`
	Params interface{} `json:"params,omitempty"`
}

Request is a message sent from prox to a plugin via stdin.

type RequestInfo

type RequestInfo struct {
	RouteID       string            `msgpack:"r"`
	Method        string            `msgpack:"m"`
	Path          string            `msgpack:"p"`
	Query         string            `msgpack:"q,omitempty"`
	Domain        string            `msgpack:"d"`
	Host          string            `msgpack:"ho,omitempty"`
	Proto         string            `msgpack:"pr,omitempty"`
	RemoteAddr    string            `msgpack:"a"`
	ContentLength int64             `msgpack:"cl,omitempty"`
	Headers       map[string]string `msgpack:"h"`
	Body          []byte            `msgpack:"bd,omitempty"`
	MatchDomain   string            `msgpack:"md,omitempty"`
	MatchGlob     string            `msgpack:"mg,omitempty"`
	MatchPath     string            `msgpack:"mp,omitempty"`
	Vars          map[string]string `msgpack:"v,omitempty"`
	Target        string            `msgpack:"tg,omitempty"`
}

RequestInfo carries the HTTP request context for on_request hooks.

type Response

type Response struct {
	Result string `json:"result,omitempty"`
	Error  string `json:"error,omitempty"`
}

Response is a simple acknowledgement from a plugin.

type ResponseModResult

type ResponseModResult struct {
	Status  int               `msgpack:"s,omitempty"`
	Headers map[string]string `msgpack:"h,omitempty"`
	Remove  []string          `msgpack:"rm,omitempty"`
}

ResponseModResult describes modifications to apply to the upstream response.

type ResponsePair

type ResponsePair struct {
	Req  RequestInfo          `msgpack:"req"`
	Resp UpstreamResponseInfo `msgpack:"resp"`
}

ResponsePair bundles request + upstream response for the on_response hook.

type RouteInfo

type RouteInfo struct {
	Action   string
	Balancer balancer.Balancer
}

RouteInfo describes a route's balancer and action for global target pushes.

type SpeedEntry

type SpeedEntry struct {
	DownloadBps int64 // bytes per second (0 = unlimited)
	UploadBps   int64 // bytes per second (0 = unlimited)
}

SpeedEntry holds per-connection bandwidth caps pushed by a plugin.

type SpeedLimit

type SpeedLimit struct {
	DownloadMbps float64 `msgpack:"dl,omitempty"`
	UploadMbps   float64 `msgpack:"ul,omitempty"`
	GroupKey     string  `msgpack:"gk,omitempty"`
}

SpeedLimit holds bandwidth caps from plugin responses. When GroupKey is set, all connections with the same key share a single budget.

type UpstreamResponseInfo

type UpstreamResponseInfo struct {
	Status  int               `msgpack:"s"`
	Headers map[string]string `msgpack:"h"`
}

UpstreamResponseInfo carries upstream response context for on_response hooks.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL