133 lines
2.4 KiB
Go
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
|
|
}
|