Files
demo/context.go
2025-03-14 18:50:49 +00:00

133 lines
2.4 KiB
Go

package goproxy
import (
"net/http"
"net/url"
"strings"
"sync"
"time"
)
// Context 代理上下文
// 包含了代理请求的上下文信息,用于在代理处理过程中传递数据
type Context struct {
// 原始请求
Req *http.Request
// 请求开始时间
StartTime time.Time
// 上下文数据,用于在各个处理阶段传递数据
Data map[interface{}]interface{}
// 是否是隧道代理
TunnelProxy bool
// 请求ID
RequestID string
// 目标地址
TargetAddr string
// 上级代理地址
ParentProxyURL *url.URL
// 是否中断执行
abort bool
// 请求标签,用于标记请求类型
Tags []string
// 是否已中止
aborted bool
// 互斥锁
mu sync.RWMutex
}
// IsHTTPS 是否是HTTPS请求
func (c *Context) IsHTTPS() bool {
return c.Req.URL.Scheme == "https" || c.Req.Method == http.MethodConnect
}
// defaultPorts 默认端口映射
var defaultPorts = map[string]string{
"https": "443",
"http": "80",
"": "80",
}
// WebSocketURL 获取WebSocket URL
func (c *Context) WebSocketURL() *url.URL {
u := *c.Req.URL
if c.IsHTTPS() {
u.Scheme = "wss"
} else {
u.Scheme = "ws"
}
return &u
}
// Addr 获取请求地址
func (c *Context) Addr() string {
addr := c.Req.Host
if !strings.Contains(c.Req.URL.Host, ":") {
addr += ":" + defaultPorts[c.Req.URL.Scheme]
}
return addr
}
// AddTag 添加请求标签
func (c *Context) AddTag(tag string) {
c.Tags = append(c.Tags, tag)
}
// HasTag 检查是否包含指定标签
func (c *Context) HasTag(tag string) bool {
for _, t := range c.Tags {
if t == tag {
return true
}
}
return false
}
// Abort 中断执行
func (c *Context) Abort() {
c.aborted = true
}
// IsAborted 是否已中断执行
func (c *Context) IsAborted() bool {
return c.aborted
}
// Reset 重置上下文
func (c *Context) Reset(req *http.Request) {
c.Req = req
c.StartTime = time.Now()
c.Data = make(map[interface{}]interface{})
c.abort = false
c.TunnelProxy = false
c.Tags = make([]string, 0)
c.RequestID = ""
c.TargetAddr = ""
c.ParentProxyURL = nil
c.aborted = false
}
// Set 设置数据
func (c *Context) Set(key, value interface{}) {
c.mu.Lock()
defer c.mu.Unlock()
if c.Data == nil {
c.Data = make(map[interface{}]interface{})
}
c.Data[key] = value
}
// Get 获取数据
func (c *Context) Get(key interface{}) (interface{}, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
if c.Data == nil {
return nil, false
}
val, ok := c.Data[key]
return val, ok
}