diff --git a/config.go b/config.go index 4bd6f22..426fad9 100644 --- a/config.go +++ b/config.go @@ -2,8 +2,6 @@ package service import ( "path/filepath" - "regexp" - "strings" ) // CertSet SSL 证书配置 @@ -90,14 +88,7 @@ func ApplyConfig() { } newProxies := make([]*proxyType, 0, len(rules)) for _, r := range rules { - p := &proxyType{authLevel: r.AuthLevel, fromPath: r.Path, toApp: r.ToApp, toPath: r.ToPath} - if strings.ContainsRune(r.Path, '(') { - matcher, err := regexp.Compile("^" + r.Path + "$") - if err == nil { - p.matcher = matcher - } - } - newProxies = append(newProxies, p) + newProxies = append(newProxies, parseProxyRule(r.AuthLevel, r.Path, r.ToApp, r.ToPath)) } fileProxies[host] = newProxies rebuildProxiesUnderLock(host) @@ -109,14 +100,7 @@ func ApplyConfig() { } newRewrites := make([]*rewriteType, 0, len(rules)) for _, r := range rules { - s := &rewriteType{fromPath: r.Path, toPath: r.ToPath} - if strings.ContainsRune(r.Path, '(') { - matcher, err := regexp.Compile("^" + r.Path + "$") - if err == nil { - s.matcher = matcher - } - } - newRewrites = append(newRewrites, s) + newRewrites = append(newRewrites, parseRewriteRule(r.Path, r.ToPath)) } fileRewrites[host] = newRewrites rebuildRewritesUnderLock(host) diff --git a/proxy.go b/proxy.go index 3d36148..bb52fda 100644 --- a/proxy.go +++ b/proxy.go @@ -12,21 +12,37 @@ import ( ) type proxyType struct { - matcher *regexp.Regexp - authLevel int - fromPath string - toApp string - toPath string + matcher *regexp.Regexp + authLevel int + fromPath string + toApp string + toPath string + hasWildcard bool + prefix string + toPrefix string } -func (hc *HostContext) Proxy(authLevel int, path string, toApp, toPath string) *HostContext { +func parseProxyRule(authLevel int, path, toApp, toPath string) *proxyType { p := &proxyType{authLevel: authLevel, fromPath: path, toApp: toApp, toPath: toPath} - if strings.Contains(path, "(") { + if strings.ContainsRune(path, '(') { matcher, err := regexp.Compile("^" + path + "$") if err == nil { p.matcher = matcher } + } else if strings.HasSuffix(path, "/*") { + p.hasWildcard = true + p.prefix = path[:len(path)-1] + if strings.HasSuffix(toPath, "/*") { + p.toPrefix = toPath[:len(toPath)-1] + } else { + p.toPrefix = toPath + } } + return p +} + +func (hc *HostContext) Proxy(authLevel int, path string, toApp, toPath string) *HostContext { + p := parseProxyRule(authLevel, path, toApp, toPath) hostPoliciesLock.Lock() defer hostPoliciesLock.Unlock() @@ -71,12 +87,7 @@ func findProxy(request *Request) (int, *string, *string, string) { } for _, pi := range proxies { - if pi.matcher == nil { - if pi.fromPath == requestPath { - toPath := pi.toPath + queryString - return pi.authLevel, &pi.toApp, &toPath, h - } - } else { + if pi.matcher != nil { finds := pi.matcher.FindAllStringSubmatch(requestPath, 1) if len(finds) > 0 { toApp := pi.toApp @@ -88,6 +99,18 @@ func findProxy(request *Request) (int, *string, *string, string) { toPath += queryString return pi.authLevel, &toApp, &toPath, h } + } else if pi.hasWildcard { + if strings.HasPrefix(requestPath, pi.prefix) { + suffix := requestPath[len(pi.prefix):] + toPath := pi.toPrefix + suffix + queryString + toApp := pi.toApp + return pi.authLevel, &toApp, &toPath, h + } + } else { + if pi.fromPath == requestPath { + toPath := pi.toPath + queryString + return pi.authLevel, &pi.toApp, &toPath, h + } } } } @@ -184,14 +207,7 @@ type ProxyRule struct { func ReplaceProxies(host string, rules []ProxyRule) { newProxies := make([]*proxyType, 0, len(rules)) for _, r := range rules { - p := &proxyType{authLevel: r.AuthLevel, fromPath: r.Path, toApp: r.ToApp, toPath: r.ToPath} - if strings.ContainsRune(r.Path, '(') { - matcher, err := regexp.Compile("^" + r.Path + "$") - if err == nil { - p.matcher = matcher - } - } - newProxies = append(newProxies, p) + newProxies = append(newProxies, parseProxyRule(r.AuthLevel, r.Path, r.ToApp, r.ToPath)) } hostPoliciesLock.Lock() diff --git a/rewrite.go b/rewrite.go index 3ac6699..57df6aa 100644 --- a/rewrite.go +++ b/rewrite.go @@ -9,20 +9,35 @@ import ( ) type rewriteType struct { - matcher *regexp.Regexp - fromPath string - toPath string + matcher *regexp.Regexp + fromPath string + toPath string + hasWildcard bool + prefix string + toPrefix string } -func (hc *HostContext) Rewrite(path string, toPath string) *HostContext { - s := &rewriteType{fromPath: path, toPath: toPath} - - if strings.ContainsRune(path, '(') { - matcher, err := regexp.Compile("^" + path + "$") +func parseRewriteRule(fromPath, toPath string) *rewriteType { + s := &rewriteType{fromPath: fromPath, toPath: toPath} + if strings.ContainsRune(fromPath, '(') { + matcher, err := regexp.Compile("^" + fromPath + "$") if err == nil { s.matcher = matcher } + } else if strings.HasSuffix(fromPath, "/*") { + s.hasWildcard = true + s.prefix = fromPath[:len(fromPath)-1] + if strings.HasSuffix(toPath, "/*") { + s.toPrefix = toPath[:len(toPath)-1] + } else { + s.toPrefix = toPath + } } + return s +} + +func (hc *HostContext) Rewrite(path string, toPath string) *HostContext { + s := parseRewriteRule(path, toPath) hostPoliciesLock.Lock() defer hostPoliciesLock.Unlock() @@ -68,12 +83,7 @@ func processRewrite(request *Request, response *Response, logger *log.Logger) bo found := false rewriteToPath := "" - if ri.matcher == nil { - if ri.fromPath == requestPath { - rewriteToPath = ri.toPath - found = true - } - } else { + if ri.matcher != nil { finds := ri.matcher.FindAllStringSubmatch(request.RequestURI, 1) if len(finds) > 0 { toPath := ri.toPath @@ -83,6 +93,17 @@ func processRewrite(request *Request, response *Response, logger *log.Logger) bo rewriteToPath = toPath found = true } + } else if ri.hasWildcard { + if strings.HasPrefix(requestPath, ri.prefix) { + suffix := requestPath[len(ri.prefix):] + rewriteToPath = ri.toPrefix + suffix + found = true + } + } else { + if ri.fromPath == requestPath { + rewriteToPath = ri.toPath + found = true + } } if found { @@ -121,14 +142,7 @@ type RewriteRule struct { func ReplaceRewrites(host string, rules []RewriteRule) { newRewrites := make([]*rewriteType, 0, len(rules)) for _, r := range rules { - s := &rewriteType{fromPath: r.Path, toPath: r.ToPath} - if strings.ContainsRune(r.Path, '(') { - matcher, err := regexp.Compile("^" + r.Path + "$") - if err == nil { - s.matcher = matcher - } - } - newRewrites = append(newRewrites, s) + newRewrites = append(newRewrites, parseRewriteRule(r.Path, r.ToPath)) } hostPoliciesLock.Lock()