diff --git a/README.md b/README.md index c916688..a0e115c 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,6 @@ GoProxy是一个功能强大的Go语言HTTP代理库,支持HTTP、HTTPS和WebS - 后端响应时间 - 支持自定义处理逻辑(委托模式) - 支持DNS缓存 -- 支持URL重写(反向代理模式) -- 支持插件系统 - - 动态加载插件 - - 插件生命周期管理 - - 插件间通信 - - 插件配置管理 - 支持认证授权 - JWT认证 - 基于角色的访问控制 @@ -485,9 +479,8 @@ resolver.Clear() GoProxy采用模块化设计,主要包含以下模块: - **代理核心(Proxy)**:处理HTTP请求和响应,实现代理功能 -- **反向代理(ReverseProxy)**:处理反向代理请求,支持URL重写和请求修改 +- **反向代理(ReverseProxy)**:处理反向代理请求,支持请求修改 - **路由(Router)**:基于主机名、路径、正则表达式等规则路由请求到不同的后端 -- **URL重写(Rewriter)**:重写请求URL和响应中的URL - **代理上下文(Context)**:保存请求上下文信息,用于在处理过程中传递数据 - **代理委托(Delegate)**:定义代理处理请求的各个阶段的回调方法,用于自定义处理逻辑 - **连接缓冲区(ConnBuffer)**:封装网络连接,提供缓冲读写功能 @@ -577,7 +570,6 @@ GoProxy 提供了以下 With 方法用于配置代理的各个方面: - `WithReverseProxy(enable bool)`: 启用反向代理模式 - `WithEnableRetry(maxRetries int, baseBackoff, maxBackoff time.Duration)`: 启用请求重试 - `WithRateLimit(rps float64)`: 设置请求限流 -- `WithURLRewrite(enable bool)`: 启用URL重写 - `WithEnableCORS(enable bool)`: 启用CORS支持 #### 证书相关选项 @@ -644,7 +636,6 @@ GoProxy提供了多个扩展点,可以通过实现相应的接口进行扩展 GoProxy的反向代理模式提供以下特性: -- **URL重写**:支持基于前缀和正则表达式的URL重写 - **路由规则**:支持基于主机名、路径、正则表达式等的路由规则 - **请求修改**:支持修改发往后端服务器的请求 - **响应修改**:支持修改来自后端服务器的响应 @@ -844,82 +835,6 @@ func main() { - 自动处理压缩请求体 - 自动添加压缩相关响应头 -## 使用插件系统 - -GoProxy提供了插件系统,支持动态加载和管理插件: - -```go -package main - -import ( - "log" - "net/http" - - "github.com/darkit/goproxy/internal/plugin" - "github.com/darkit/goproxy/internal/proxy" -) - -func main() { - // 创建插件管理器 - pluginManager := plugin.NewPluginManager("./plugins") - - // 加载插件 - if err := pluginManager.LoadPlugins(); err != nil { - log.Printf("加载插件失败: %v", err) - } - - // 创建代理 - p := proxy.NewProxy( - proxy.WithPluginManager(pluginManager), - ) - - // 启动HTTP服务器 - log.Println("代理服务器启动在 :8080") - if err := http.ListenAndServe(":8080", p); err != nil { - log.Fatalf("代理服务器启动失败: %v", err) - } -} -``` - -插件示例: - -```go -// plugin.go -package main - -import ( - "context" - "log" -) - -type MyPlugin struct{} - -func (p *MyPlugin) Name() string { - return "my-plugin" -} - -func (p *MyPlugin) Version() string { - return "1.0.0" -} - -func (p *MyPlugin) Init(ctx context.Context) error { - log.Println("初始化插件") - return nil -} - -func (p *MyPlugin) Start(ctx context.Context) error { - log.Println("启动插件") - return nil -} - -func (p *MyPlugin) Stop(ctx context.Context) error { - log.Println("停止插件") - return nil -} - -var Plugin = &MyPlugin{} -``` - ### 使用认证授权系统 GoProxy提供了完整的认证授权系统,支持JWT认证和基于角色的访问控制: diff --git a/docs/api.md b/docs/api.md index 2a6197b..2836817 100644 --- a/docs/api.md +++ b/docs/api.md @@ -137,43 +137,9 @@ GET /api/v1/metrics } ``` -### 4. 插件管理 +### 4. 缓存管理 -#### 4.1 获取插件列表 - -``` -GET /api/v1/plugins -``` - -响应: -```json -{ - "plugins": [ - { - "name": "compression", - "version": "1.0.0", - "enabled": true - } - ] -} -``` - -#### 4.2 启用/禁用插件 - -``` -PUT /api/v1/plugins/{plugin_name}/status -``` - -请求体: -```json -{ - "enabled": true -} -``` - -### 5. 缓存管理 - -#### 5.1 获取缓存统计 +#### 4.1 获取缓存统计 ``` GET /api/v1/cache/stats @@ -189,15 +155,15 @@ GET /api/v1/cache/stats } ``` -#### 5.2 清除缓存 +#### 4.2 清除缓存 ``` DELETE /api/v1/cache ``` -### 6. 健康检查 +### 5. 健康检查 -#### 6.1 获取健康状态 +#### 5.1 获取健康状态 ``` GET /api/v1/health @@ -247,5 +213,4 @@ API版本通过URL路径指定,当前版本为v1。 - 初始版本 - 基本代理功能 - 用户认证 -- 监控指标 -- 插件系统 \ No newline at end of file +- 监控指标 \ No newline at end of file diff --git a/examples/dns_config.json b/docs/dns_config.json similarity index 100% rename from examples/dns_config.json rename to docs/dns_config.json diff --git a/examples/hosts.txt b/docs/hosts.txt similarity index 100% rename from examples/hosts.txt rename to docs/hosts.txt diff --git a/examples/wildcard_dns_config.json b/docs/wildcard_dns_config.json similarity index 100% rename from examples/wildcard_dns_config.json rename to docs/wildcard_dns_config.json diff --git a/examples/wildcard_hosts.txt b/docs/wildcard_hosts.txt similarity index 100% rename from examples/wildcard_hosts.txt rename to docs/wildcard_hosts.txt diff --git a/examples/plugins/example/build.sh b/examples/plugins/example/build.sh deleted file mode 100644 index 4110174..0000000 --- a/examples/plugins/example/build.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -# 编译插件 -go build -buildmode=plugin -o example.so example.go - -# 检查编译结果 -if [ $? -eq 0 ]; then - echo "插件编译成功: example.so" -else - echo "插件编译失败" - exit 1 -fi \ No newline at end of file diff --git a/examples/plugins/example/example.go b/examples/plugins/example/example.go deleted file mode 100644 index 0ea5000..0000000 --- a/examples/plugins/example/example.go +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "context" - "log" - "time" -) - -// ExamplePlugin 示例插件 -type ExamplePlugin struct { - // 插件配置 - config map[string]interface{} - // 插件状态 - running bool -} - -// Name 插件名称 -func (p *ExamplePlugin) Name() string { - return "example" -} - -// Version 插件版本 -func (p *ExamplePlugin) Version() string { - return "1.0.0" -} - -// Init 初始化插件 -func (p *ExamplePlugin) Init(ctx context.Context) error { - log.Printf("初始化插件 %s v%s\n", p.Name(), p.Version()) - - // 初始化配置 - p.config = make(map[string]interface{}) - p.config["startTime"] = time.Now() - - return nil -} - -// Start 启动插件 -func (p *ExamplePlugin) Start(ctx context.Context) error { - log.Printf("启动插件 %s\n", p.Name()) - - // 启动后台任务 - go func() { - p.running = true - ticker := time.NewTicker(5 * time.Second) - defer ticker.Stop() - - for p.running { - select { - case <-ctx.Done(): - return - case <-ticker.C: - log.Printf("插件 %s 正在运行...\n", p.Name()) - } - } - }() - - return nil -} - -// Stop 停止插件 -func (p *ExamplePlugin) Stop(ctx context.Context) error { - log.Printf("停止插件 %s\n", p.Name()) - - // 停止后台任务 - p.running = false - - // 清理资源 - if startTime, ok := p.config["startTime"].(time.Time); ok { - duration := time.Since(startTime) - log.Printf("插件 %s 运行时长: %v\n", p.Name(), duration) - } - - return nil -} - -// Plugin 导出插件实例 -var Plugin = &ExamplePlugin{} diff --git a/internal/auth/auth.go b/internal/auth/auth.go index af21931..f8efd5e 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -196,7 +196,6 @@ func (a *Auth) ValidateToken(tokenString string) (*jwt.MapClaims, error) { token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return a.secretKey, nil }) - if err != nil { return nil, err } diff --git a/internal/config/config.go b/internal/config/config.go index e33a483..d4c7bd5 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -69,8 +69,6 @@ type Config struct { ReverseProxy bool // 反向代理规则文件路径 ReverseProxyRulesFile string - // 是否启用URL重写 - EnableURLRewrite bool // 是否保留客户端IP PreserveClientIP bool // 是否启用压缩 @@ -127,7 +125,6 @@ func DefaultConfig() *Config { DNSCacheTTL: 5 * time.Minute, ReverseProxy: false, ReverseProxyRulesFile: "", - EnableURLRewrite: false, PreserveClientIP: true, EnableCompression: false, EnableCORS: false, diff --git a/internal/plugin/plugin.go b/internal/plugin/plugin.go deleted file mode 100644 index afb389d..0000000 --- a/internal/plugin/plugin.go +++ /dev/null @@ -1,162 +0,0 @@ -package plugin - -import ( - "context" - "errors" - "fmt" - "io/fs" - "os" - "path/filepath" - "plugin" - "sync" -) - -// Plugin 插件接口 -type Plugin interface { - // Name 插件名称 - Name() string - // Version 插件版本 - Version() string - // Init 初始化插件 - Init(ctx context.Context) error - // Start 启动插件 - Start(ctx context.Context) error - // Stop 停止插件 - Stop(ctx context.Context) error -} - -// PluginManager 插件管理器 -type PluginManager struct { - pluginsDir string - plugins map[string]Plugin - mu sync.RWMutex -} - -// NewPluginManager 创建插件管理器 -func NewPluginManager(pluginsDir string) *PluginManager { - return &PluginManager{ - pluginsDir: pluginsDir, - plugins: make(map[string]Plugin), - } -} - -// LoadPlugins 加载插件 -func (pm *PluginManager) LoadPlugins() error { - // 确保插件目录存在 - if err := os.MkdirAll(pm.pluginsDir, 0755); err != nil { - return fmt.Errorf("创建插件目录失败: %v", err) - } - - // 遍历插件目录 - err := filepath.Walk(pm.pluginsDir, func(path string, info fs.FileInfo, err error) error { - if err != nil { - return err - } - - // 跳过目录和非.so文件 - if info.IsDir() || filepath.Ext(path) != ".so" { - return nil - } - - // 加载插件 - if err := pm.loadPlugin(path); err != nil { - fmt.Printf("加载插件 %s 失败: %v\n", path, err) - } - - return nil - }) - - return err -} - -// loadPlugin 加载单个插件 -func (pm *PluginManager) loadPlugin(path string) error { - // 打开插件文件 - p, err := plugin.Open(path) - if err != nil { - return fmt.Errorf("打开插件失败: %v", err) - } - - // 查找Plugin变量 - symPlugin, err := p.Lookup("Plugin") - if err != nil { - return fmt.Errorf("查找Plugin变量失败: %v", err) - } - - // 类型断言 - plugin, ok := symPlugin.(Plugin) - if !ok { - return errors.New("插件类型错误") - } - - // 检查插件名称是否已存在 - pm.mu.Lock() - if _, exists := pm.plugins[plugin.Name()]; exists { - pm.mu.Unlock() - return fmt.Errorf("插件 %s 已存在", plugin.Name()) - } - pm.plugins[plugin.Name()] = plugin - pm.mu.Unlock() - - return nil -} - -// GetPlugin 获取插件 -func (pm *PluginManager) GetPlugin(name string) (Plugin, bool) { - pm.mu.RLock() - defer pm.mu.RUnlock() - - plugin, exists := pm.plugins[name] - return plugin, exists -} - -// GetAllPlugins 获取所有插件 -func (pm *PluginManager) GetAllPlugins() []Plugin { - pm.mu.RLock() - defer pm.mu.RUnlock() - - plugins := make([]Plugin, 0, len(pm.plugins)) - for _, plugin := range pm.plugins { - plugins = append(plugins, plugin) - } - return plugins -} - -// InitPlugins 初始化所有插件 -func (pm *PluginManager) InitPlugins(ctx context.Context) error { - pm.mu.RLock() - defer pm.mu.RUnlock() - - for name, plugin := range pm.plugins { - if err := plugin.Init(ctx); err != nil { - return fmt.Errorf("初始化插件 %s 失败: %v", name, err) - } - } - return nil -} - -// StartPlugins 启动所有插件 -func (pm *PluginManager) StartPlugins(ctx context.Context) error { - pm.mu.RLock() - defer pm.mu.RUnlock() - - for name, plugin := range pm.plugins { - if err := plugin.Start(ctx); err != nil { - return fmt.Errorf("启动插件 %s 失败: %v", name, err) - } - } - return nil -} - -// StopPlugins 停止所有插件 -func (pm *PluginManager) StopPlugins(ctx context.Context) error { - pm.mu.RLock() - defer pm.mu.RUnlock() - - for name, plugin := range pm.plugins { - if err := plugin.Stop(ctx); err != nil { - return fmt.Errorf("停止插件 %s 失败: %v", name, err) - } - } - return nil -} diff --git a/internal/proxy/certificate.go b/internal/proxy/certificate.go index a2c842f..79dc4ed 100644 --- a/internal/proxy/certificate.go +++ b/internal/proxy/certificate.go @@ -472,7 +472,7 @@ func SaveCertificateToFile(cert *x509.Certificate, key *ecdsa.PrivateKey, certFi Type: "CERTIFICATE", Bytes: cert.Raw, }) - if err := os.WriteFile(certFile, certPEM, 0644); err != nil { + if err := os.WriteFile(certFile, certPEM, 0o644); err != nil { return fmt.Errorf("保存证书到文件失败: %s", err) } @@ -485,7 +485,7 @@ func SaveCertificateToFile(cert *x509.Certificate, key *ecdsa.PrivateKey, certFi Type: "EC PRIVATE KEY", Bytes: keyBytes, }) - if err := os.WriteFile(keyFile, keyPEM, 0600); err != nil { + if err := os.WriteFile(keyFile, keyPEM, 0o600); err != nil { return fmt.Errorf("保存私钥到文件失败: %s", err) } diff --git a/internal/proxy/options.go b/internal/proxy/options.go index 5b40b7a..56acf69 100644 --- a/internal/proxy/options.go +++ b/internal/proxy/options.go @@ -209,16 +209,6 @@ func WithDNSCacheTTL(ttl time.Duration) Option { } } -// WithURLRewrite 启用URL重写 -func WithURLRewrite(enable bool) Option { - return func(opt *Options) { - if opt.Config == nil { - opt.Config = config.DefaultConfig() - } - opt.Config.EnableURLRewrite = enable - } -} - // WithEnableCORS 启用CORS支持 func WithEnableCORS(enable bool) Option { return func(opt *Options) { diff --git a/internal/proxy/proxy.go b/internal/proxy/proxy.go index c8addb1..e6cde52 100644 --- a/internal/proxy/proxy.go +++ b/internal/proxy/proxy.go @@ -25,7 +25,6 @@ import ( "github.com/darkit/goproxy/internal/loadbalance" "github.com/darkit/goproxy/internal/metrics" "github.com/darkit/goproxy/internal/middleware" - "github.com/darkit/goproxy/internal/plugin" "github.com/darkit/goproxy/internal/reverse" "github.com/ouqiang/websocket" "github.com/viki-org/dnscache" @@ -204,8 +203,6 @@ type Options struct { ClientTrace *httptrace.ClientTrace // 认证系统 Auth *auth.Auth - // 插件管理器 - PluginManager *plugin.PluginManager // 证书管理器 CertManager *CertManager } @@ -217,13 +214,6 @@ func WithAuth(auth *auth.Auth) Option { } } -// WithPluginManager 设置插件管理器 -func WithPluginManager(pluginManager *plugin.PluginManager) Option { - return func(o *Options) { - o.PluginManager = pluginManager - } -} - // Proxy HTTP代理 type Proxy struct { // 配置 @@ -499,7 +489,6 @@ func (p *Proxy) handleHTTP(ctx *Context, rw http.ResponseWriter) { // 发送请求 var err error resp, err = p.httpTransport.RoundTrip(req) - // 处理错误 if err != nil { p.delegate.BeforeResponse(ctx, nil, err) diff --git a/internal/rewriter/rewriter.go b/internal/rewriter/rewriter.go deleted file mode 100644 index d89093b..0000000 --- a/internal/rewriter/rewriter.go +++ /dev/null @@ -1,98 +0,0 @@ -package rewriter - -import ( - "net/http" - "regexp" - "strings" -) - -// Rewriter URL重写器 -// 用于在反向代理中重写请求URL -type Rewriter struct { - // 重写规则列表 - rules []*RewriteRule -} - -// RewriteRule 重写规则 -type RewriteRule struct { - // 匹配模式 - Pattern string - // 替换模式 - Replacement string - // 是否使用正则表达式 - UseRegex bool - // 编译后的正则表达式 - regex *regexp.Regexp -} - -// NewRewriter 创建URL重写器 -func NewRewriter() *Rewriter { - return &Rewriter{ - rules: make([]*RewriteRule, 0), - } -} - -// AddRule 添加重写规则 -func (r *Rewriter) AddRule(pattern, replacement string, useRegex bool) error { - rule := &RewriteRule{ - Pattern: pattern, - Replacement: replacement, - UseRegex: useRegex, - } - - if useRegex { - regex, err := regexp.Compile(pattern) - if err != nil { - return err - } - rule.regex = regex - } - - r.rules = append(r.rules, rule) - return nil -} - -// Rewrite 重写URL -func (r *Rewriter) Rewrite(req *http.Request) { - path := req.URL.Path - - for _, rule := range r.rules { - if rule.UseRegex { - if rule.regex.MatchString(path) { - req.URL.Path = rule.regex.ReplaceAllString(path, rule.Replacement) - break - } - } else { - if strings.HasPrefix(path, rule.Pattern) { - req.URL.Path = strings.Replace(path, rule.Pattern, rule.Replacement, 1) - break - } - } - } -} - -// RewriteResponse 重写响应 -// 主要用于处理响应中的Location头和内容中的URL -func (r *Rewriter) RewriteResponse(resp *http.Response, originHost string) { - // 处理重定向头 - location := resp.Header.Get("Location") - if location != "" { - // 将后端服务器的域名替换成代理服务器的域名 - for _, rule := range r.rules { - if rule.UseRegex && rule.regex != nil { - if rule.regex.MatchString(location) { - newLocation := rule.regex.ReplaceAllString(location, rule.Replacement) - resp.Header.Set("Location", newLocation) - break - } - } - } - } -} - -// LoadRulesFromFile 从文件加载重写规则 -func (r *Rewriter) LoadRulesFromFile(filename string) error { - // 实现从配置文件加载规则的逻辑 - // 这里省略实现细节 - return nil -}