proxy: precompile regexp

This commit is contained in:
sputn1ck
2025-05-14 20:51:21 +02:00
parent 4e5a50a0b8
commit 1557c4aef9
2 changed files with 40 additions and 7 deletions

View File

@@ -8,7 +8,6 @@ import (
"net/http"
"net/http/httputil"
"os"
"regexp"
"strconv"
"strings"
@@ -366,21 +365,21 @@ func certPool(services []*Service) (*x509.CertPool, error) {
// expression matching the host and path.
func matchService(req *http.Request, services []*Service) (*Service, bool) {
for _, service := range services {
hostRegexp := regexp.MustCompile(service.HostRegexp)
hostRegexp := service.compiledHostRegexp
if !hostRegexp.MatchString(req.Host) {
log.Tracef("Req host [%s] doesn't match [%s].",
req.Host, hostRegexp)
continue
}
if service.PathRegexp == "" {
if service.compiledPathRegexp == nil {
log.Debugf("Host [%s] matched pattern [%s] and path "+
"expression is empty. Using service [%s].",
req.Host, hostRegexp, service.Address)
return service, true
}
pathRegexp := regexp.MustCompile(service.PathRegexp)
pathRegexp := service.compiledPathRegexp
if !pathRegexp.MatchString(req.URL.Path) {
log.Tracef("Req path [%s] doesn't match [%s].",
req.URL.Path, pathRegexp)

View File

@@ -103,6 +103,15 @@ type Service struct {
// /package_name.ServiceName/MethodName
AuthWhitelistPaths []string `long:"authwhitelistpaths" description:"List of regular expressions for paths that don't require authentication'"`
// compiledHostRegexp is the compiled host regex.
compiledHostRegexp *regexp.Regexp
// compiledPathRegexp is the compiled path regex.
compiledPathRegexp *regexp.Regexp
// compiledAuthWhitelistPaths is the compiled auth whitelist paths.
compiledAuthWhitelistPaths []*regexp.Regexp
freebieDB freebie.DB
pricer pricer.Pricer
}
@@ -123,8 +132,7 @@ func (s *Service) ResourceName(resourcePath string) string {
// AuthRequired determines the auth level required for a given request.
func (s *Service) AuthRequired(r *http.Request) auth.Level {
// Does the request match any whitelist entry?
for _, pathRegexp := range s.AuthWhitelistPaths {
pathRegexp := regexp.MustCompile(pathRegexp)
for _, pathRegexp := range s.compiledAuthWhitelistPaths {
if pathRegexp.MatchString(r.URL.Path) {
log.Tracef("Req path [%s] matches whitelist entry "+
"[%s].", r.URL.Path, pathRegexp)
@@ -184,15 +192,41 @@ func prepareServices(services []*Service) error {
}
}
// Compile the host regex.
compiledHostRegexp, err := regexp.Compile(service.HostRegexp)
if err != nil {
return fmt.Errorf("error compiling host regex: %v", err)
}
service.compiledHostRegexp = compiledHostRegexp
// Compile the path regex.
if service.PathRegexp != "" {
compiledPathRegexp, err := regexp.Compile(
service.PathRegexp,
)
if err != nil {
return fmt.Errorf("error compiling path "+
"regex: %v", err)
}
service.compiledPathRegexp = compiledPathRegexp
}
service.compiledAuthWhitelistPaths = make(
[]*regexp.Regexp, 0, len(service.AuthWhitelistPaths),
)
// Make sure all whitelist regular expression entries actually
// compile so we run into an eventual panic during startup and
// not only when the request happens.
for _, entry := range service.AuthWhitelistPaths {
_, err := regexp.Compile(entry)
regExp, err := regexp.Compile(entry)
if err != nil {
return fmt.Errorf("error validating auth "+
"whitelist: %v", err)
}
service.compiledAuthWhitelistPaths = append(
service.compiledAuthWhitelistPaths, regExp,
)
}
// If dynamic prices are enabled then use the provided