Files
Wormhole/internal/forwardplugin/plugin.go
T
rose_cat707 612d68f56f feat: Wormhole 内网穿透与反向代理网关
Go + Vue 管理台,SQLite 持久化;支持隧道/域名穿透、域名转发插件链、访客认证、
IP 规则、API Key、Docker 单镜像部署;配置通过 Web 系统设置管理,无需 YAML 文件。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 12:15:02 +08:00

119 lines
2.2 KiB
Go

package forwardplugin
import (
"encoding/json"
"net/http"
"sync"
)
type PluginEntry struct {
Type string `json:"type"`
Enabled bool `json:"enabled"`
Config json.RawMessage `json:"config"`
}
type Plugin interface {
Type() string
ValidateConfig(raw json.RawMessage) error
NeedsBody() bool
HandleRequest(ctx *Context, req *http.Request) (shortCircuit bool, err error)
HandleResponse(ctx *Context, resp *BufferedResponse) error
}
type PluginFactory func(config json.RawMessage) (Plugin, error)
type RawStorer interface {
StoreRaw(ctx *Context, resp *BufferedResponse)
}
var (
registryMu sync.RWMutex
registry = map[string]PluginFactory{}
)
func Register(typ string, factory PluginFactory) {
registryMu.Lock()
defer registryMu.Unlock()
registry[typ] = factory
}
func getFactory(typ string) (PluginFactory, bool) {
registryMu.RLock()
defer registryMu.RUnlock()
f, ok := registry[typ]
return f, ok
}
type Context struct {
ForwardID uint
ClientReq *http.Request
CachedResp *BufferedResponse
}
type BufferedResponse struct {
StatusCode int
Header http.Header
Body []byte
FromCache bool
}
func (r *BufferedResponse) Clone() *BufferedResponse {
if r == nil {
return nil
}
h := r.Header.Clone()
return &BufferedResponse{
StatusCode: r.StatusCode,
Header: h,
Body: append([]byte(nil), r.Body...),
FromCache: r.FromCache,
}
}
type Chain struct {
plugins []Plugin
}
func (c *Chain) Empty() bool {
return c == nil || len(c.plugins) == 0
}
func (c *Chain) NeedsBody() bool {
for _, p := range c.plugins {
if p.NeedsBody() {
return true
}
}
return false
}
func (c *Chain) HandleRequest(ctx *Context, req *http.Request) (bool, error) {
for _, p := range c.plugins {
short, err := p.HandleRequest(ctx, req)
if err != nil {
return false, err
}
if short {
return true, nil
}
}
return false, nil
}
func (c *Chain) StoreRawResponses(ctx *Context, resp *BufferedResponse) {
for _, p := range c.plugins {
if st, ok := p.(RawStorer); ok {
st.StoreRaw(ctx, resp)
}
}
}
func (c *Chain) HandleResponse(ctx *Context, resp *BufferedResponse) error {
for _, p := range c.plugins {
if err := p.HandleResponse(ctx, resp); err != nil {
return err
}
}
return nil
}