package proxy import ( "github.com/astaxie/beego/context" "github.com/astaxie/beego/logs" "net/http" "net/url" "nginx-ui/server/models" "regexp" "strings" ) type Data struct { *models.ProxyEntity Regexp []*regexp.Regexp `orm:"-" json:"-"` proxy *HttpProxy wsProxy *WebsocketProxy } type ReverseProxy struct { proxies []*Data NoProxies []*regexp.Regexp `json:"-"` } func NewReverseProxy() *ReverseProxy { return &ReverseProxy{ proxies: make([]*Data, 0), NoProxies: make([]*regexp.Regexp, 0), } } func (proxy *ReverseProxy) AddNoProxy(pattern *regexp.Regexp) { proxy.NoProxies = append(proxy.NoProxies, pattern) } func (proxy *ReverseProxy) proxy(ctx *context.Context, data *Data) { if data.wsProxy != nil { if data.wsProxy.Proxy(ctx.ResponseWriter, ctx.Request) { return } } data.proxy.ServeHTTP(ctx.ResponseWriter, ctx.Request) } func (proxy *ReverseProxy) LoadProxies(list []*models.ProxyEntity) { entities := make([]*Data, 0) for _, p := range list { data := &Data{ProxyEntity: p} items := make([]*regexp.Regexp, 0) patterns := strings.Split(p.Patterns, ",") for _, pattern := range patterns { reg, err := regexp.Compile(pattern) if err != nil { logs.Error("regexp error: %s", err) continue } items = append(items, reg) } data.Regexp = items parsedURL, err := url.Parse(p.Target) if err != nil { logs.Error("target parse url error: %s", err) continue } data.proxy = NewSingleHostReverseProxy(parsedURL, p) if len(p.Ws) > 0 { ws, err := NewWebsocketProxy(p.Ws, func(r *http.Request) error { return nil }) if err != nil { logs.Error("NewWebsocketProxy fail: %v", err) } else { data.wsProxy = ws } } entities = append(entities, data) } proxy.proxies = entities } func (proxy *ReverseProxy) Filter(ctx *context.Context) { request := ctx.Request.RequestURI for _, n := range proxy.NoProxies { if n.MatchString(request) { return } } for _, p := range proxy.proxies { for _, pattern := range p.Regexp { if pattern.MatchString(request) { proxy.proxy(ctx, p) return } } } }