enable domain matching, removed unnecessary path_pattern check

This commit is contained in:
yusing 2024-12-02 04:39:46 +08:00
parent 58cfba7695
commit 3f9d73d784
5 changed files with 29 additions and 100 deletions

View file

@ -0,0 +1,21 @@
package http
import "net/http"
type ServeMux struct {
*http.ServeMux
}
func NewServeMux() ServeMux {
return ServeMux{http.NewServeMux()}
}
func (mux ServeMux) HandleFunc(pattern string, handler http.HandlerFunc) (err error) {
defer func() {
if r := recover(); r != nil {
err = r.(error)
}
}()
mux.ServeMux.HandleFunc(pattern, handler)
return
}

View file

@ -20,7 +20,7 @@ type ReverseProxyEntry struct { // real model after validation
Scheme route.Scheme `json:"scheme"` Scheme route.Scheme `json:"scheme"`
URL net.URL `json:"url"` URL net.URL `json:"url"`
NoTLSVerify bool `json:"no_tls_verify,omitempty"` NoTLSVerify bool `json:"no_tls_verify,omitempty"`
PathPatterns route.PathPatterns `json:"path_patterns,omitempty"` PathPatterns []string `json:"path_patterns,omitempty"`
HealthCheck *health.HealthCheckConfig `json:"healthcheck,omitempty"` HealthCheck *health.HealthCheckConfig `json:"healthcheck,omitempty"`
LoadBalance *loadbalance.Config `json:"load_balance,omitempty"` LoadBalance *loadbalance.Config `json:"load_balance,omitempty"`
Middlewares map[string]docker.LabelMap `json:"middlewares,omitempty"` Middlewares map[string]docker.LabelMap `json:"middlewares,omitempty"`
@ -66,7 +66,6 @@ func validateRPEntry(m *route.RawEntry, s route.Scheme, errs *E.Builder) *Revers
host := E.Collect(errs, route.ValidateHost, m.Host) host := E.Collect(errs, route.ValidateHost, m.Host)
port := E.Collect(errs, route.ValidatePort, m.Port) port := E.Collect(errs, route.ValidatePort, m.Port)
pathPats := E.Collect(errs, route.ValidatePathPatterns, m.PathPatterns)
url := E.Collect(errs, url.Parse, fmt.Sprintf("%s://%s:%d", s, host, port)) url := E.Collect(errs, url.Parse, fmt.Sprintf("%s://%s:%d", s, host, port))
iwCfg := E.Collect(errs, idlewatcher.ValidateConfig, cont) iwCfg := E.Collect(errs, idlewatcher.ValidateConfig, cont)
@ -80,7 +79,7 @@ func validateRPEntry(m *route.RawEntry, s route.Scheme, errs *E.Builder) *Revers
Scheme: s, Scheme: s,
URL: net.NewURL(url), URL: net.NewURL(url),
NoTLSVerify: m.NoTLSVerify, NoTLSVerify: m.NoTLSVerify,
PathPatterns: pathPats, PathPatterns: m.PathPatterns,
HealthCheck: m.HealthCheck, HealthCheck: m.HealthCheck,
LoadBalance: lb, LoadBalance: lb,
Middlewares: m.Middlewares, Middlewares: m.Middlewares,

View file

@ -102,9 +102,13 @@ func (r *HTTPRoute) Start(providerSubtask task.Task) E.Error {
case len(r.PathPatterns) == 1 && r.PathPatterns[0] == "/": case len(r.PathPatterns) == 1 && r.PathPatterns[0] == "/":
r.handler = r.rp r.handler = r.rp
default: default:
mux := http.NewServeMux() mux := gphttp.NewServeMux()
patErrs := E.NewBuilder("invalid path pattern(s)")
for _, p := range r.PathPatterns { for _, p := range r.PathPatterns {
mux.HandleFunc(string(p), r.rp.HandlerFunc) patErrs.Add(mux.HandleFunc(p, r.rp.HandlerFunc))
}
if err := patErrs.Error(); err != nil {
return err
} }
r.handler = mux r.handler = mux
} }

View file

@ -1,48 +0,0 @@
package types
import (
"errors"
"fmt"
"regexp"
E "github.com/yusing/go-proxy/internal/error"
)
type (
PathPattern string
PathPatterns = []PathPattern
)
var pathPattern = regexp.MustCompile(`^(/[-\w./]*({\$\})?|((GET|POST|DELETE|PUT|HEAD|OPTION) /[-\w./]*({\$\})?))$`)
var (
ErrEmptyPathPattern = errors.New("path must not be empty")
ErrInvalidPathPattern = errors.New("invalid path pattern")
)
func ValidatePathPattern(s string) (PathPattern, error) {
if len(s) == 0 {
return "", ErrEmptyPathPattern
}
if !pathPattern.MatchString(s) {
return "", fmt.Errorf("%w %q", ErrInvalidPathPattern, s)
}
return PathPattern(s), nil
}
func ValidatePathPatterns(s []string) (PathPatterns, E.Error) {
if len(s) == 0 {
return nil, nil
}
errs := E.NewBuilder("invalid path patterns")
pp := make(PathPatterns, len(s))
for i, v := range s {
pattern, err := ValidatePathPattern(v)
if err != nil {
errs.Add(err)
} else {
pp[i] = pattern
}
}
return pp, errs.Error()
}

View file

@ -1,47 +0,0 @@
package types
import (
"errors"
"testing"
U "github.com/yusing/go-proxy/internal/utils/testing"
)
var validPatterns = []string{
"/",
"/index.html",
"/somepage/",
"/drive/abc.mp4",
"/{$}",
"/some-page/{$}",
"GET /",
"GET /static/{$}",
"GET /drive/abc.mp4",
"GET /drive/abc.mp4/{$}",
"POST /auth",
"DELETE /user/",
"PUT /storage/id/",
}
var invalidPatterns = []string{
"/$",
"/{$}{$}",
"/{$}/{$}",
"/index.html$",
"get /",
"GET/",
"GET /$",
"GET /drive/{$}/abc.mp4/",
"OPTION /config/{$}/abc.conf/{$}",
}
func TestPathPatternRegex(t *testing.T) {
for _, pattern := range validPatterns {
_, err := ValidatePathPattern(pattern)
U.ExpectNoError(t, err)
}
for _, pattern := range invalidPatterns {
_, err := ValidatePathPattern(pattern)
U.ExpectTrue(t, errors.Is(err, ErrInvalidPathPattern))
}
}