612d68f56f
Go + Vue 管理台,SQLite 持久化;支持隧道/域名穿透、域名转发插件链、访客认证、 IP 规则、API Key、Docker 单镜像部署;配置通过 Web 系统设置管理,无需 YAML 文件。 Co-authored-by: Cursor <cursoragent@cursor.com>
87 lines
2.0 KiB
Go
87 lines
2.0 KiB
Go
package forwardplugin
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
func init() {
|
|
Register("cookie_domain", newCookieDomainPlugin)
|
|
}
|
|
|
|
type cookieDomainConfig struct {
|
|
From string `json:"from"`
|
|
To string `json:"to"`
|
|
}
|
|
|
|
type cookieDomainPlugin struct {
|
|
from string
|
|
to string
|
|
}
|
|
|
|
func newCookieDomainPlugin(raw json.RawMessage) (Plugin, error) {
|
|
var cfg cookieDomainConfig
|
|
if err := json.Unmarshal(raw, &cfg); err != nil {
|
|
return nil, fmt.Errorf("cookie_domain 配置无效")
|
|
}
|
|
return &cookieDomainPlugin{from: cfg.From, to: cfg.To}, nil
|
|
}
|
|
|
|
func (p *cookieDomainPlugin) Type() string { return "cookie_domain" }
|
|
|
|
func (p *cookieDomainPlugin) ValidateConfig(raw json.RawMessage) error {
|
|
var cfg cookieDomainConfig
|
|
if err := json.Unmarshal(raw, &cfg); err != nil {
|
|
return fmt.Errorf("cookie_domain 配置无效")
|
|
}
|
|
if strings.TrimSpace(cfg.From) == "" {
|
|
return fmt.Errorf("cookie_domain.from 不能为空")
|
|
}
|
|
if strings.TrimSpace(cfg.To) == "" {
|
|
return fmt.Errorf("cookie_domain.to 不能为空")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *cookieDomainPlugin) NeedsBody() bool { return false }
|
|
|
|
func (p *cookieDomainPlugin) HandleRequest(_ *Context, _ *http.Request) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
func (p *cookieDomainPlugin) HandleResponse(_ *Context, resp *BufferedResponse) error {
|
|
cookies := resp.Header.Values("Set-Cookie")
|
|
if len(cookies) == 0 {
|
|
return nil
|
|
}
|
|
resp.Header.Del("Set-Cookie")
|
|
for _, c := range cookies {
|
|
resp.Header.Add("Set-Cookie", rewriteCookieDomain(c, p.from, p.to))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func rewriteCookieDomain(cookie, from, to string) string {
|
|
parts := strings.Split(cookie, ";")
|
|
for i, part := range parts {
|
|
trimmed := strings.TrimSpace(part)
|
|
kv := strings.SplitN(trimmed, "=", 2)
|
|
if len(kv) != 2 {
|
|
continue
|
|
}
|
|
if strings.EqualFold(kv[0], "domain") {
|
|
val := strings.TrimSpace(kv[1])
|
|
if val == from || strings.TrimPrefix(val, ".") == strings.TrimPrefix(from, ".") {
|
|
parts[i] = "Domain=" + to
|
|
} else {
|
|
parts[i] = trimmed
|
|
}
|
|
} else {
|
|
parts[i] = trimmed
|
|
}
|
|
}
|
|
return strings.Join(parts, "; ")
|
|
}
|