Skip to content

Commit

Permalink
Optimize URL rewriting by compiling regex once during BackendService …
Browse files Browse the repository at this point in the history
…initialization (#105)

* use a pre compiled regex

* changes suggested by amit

* fix test

* refactor compile path

* add validation function for regex

* removed error returned

* private compile function
  • Loading branch information
Aaron Parfitt authored Apr 9, 2023
1 parent 186d06d commit ede404c
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
21 changes: 20 additions & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package api
import (
"encoding/json"
"fmt"
"github.com/Frontman-Labs/frontman/loadbalancer"
"net/http"
"net/url"
"regexp"

"github.com/Frontman-Labs/frontman/loadbalancer"

"github.com/Frontman-Labs/frontman/service"
"github.com/julienschmidt/httprouter"
Expand Down Expand Up @@ -174,6 +176,11 @@ func validateService(service *service.BackendService) error {
return err
}

err = validateMatchPath(service)
if err != nil {
return err
}

service.Init()

return nil
Expand Down Expand Up @@ -201,6 +208,18 @@ func validateLoadBalancerPolicy(s *service.BackendService) error {
return nil
}

func validateMatchPath(bs *service.BackendService) error {
if bs.RewriteMatch == "" || bs.RewriteReplace == "" {
return nil
}
_, err := regexp.Compile(bs.RewriteMatch)
if err != nil {
return err
}

return nil
}

func prepareHeaders(w http.ResponseWriter, code int) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
Expand Down
11 changes: 3 additions & 8 deletions gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"io"
"net/http"
"net/url"
"regexp"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -66,13 +65,9 @@ func (g *APIGateway) ServeHTTP(w http.ResponseWriter, req *http.Request) {
urlPath = req.URL.Path
}

if backendService.RewriteMatch != "" && backendService.RewriteReplace != "" {
re, err := regexp.Compile(backendService.RewriteMatch)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
urlPath = re.ReplaceAllString(urlPath, backendService.RewriteReplace)
// Use the compiledRegex field in the backendService struct to apply the rewrite
if backendService.GetCompiledRewriteMatch() != nil {
urlPath = backendService.GetCompiledRewriteMatch().ReplaceAllString(urlPath, backendService.RewriteReplace)
}

// Create a new target URL with the service path and scheme
Expand Down
35 changes: 32 additions & 3 deletions service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"log"
"net/http"
"time"
"regexp"

"github.com/Frontman-Labs/frontman/auth"
"github.com/Frontman-Labs/frontman/config"
Expand All @@ -29,9 +30,11 @@ type BackendService struct {
RewriteMatch string `json:"rewriteMatch,omitempty" yaml:"rewriteMatch,omitempty"`
RewriteReplace string `json:"rewriteReplace,omitempty" yaml:"rewriteReplace,omitempty"`

loadBalancer loadbalancer.LoadBalancer
provider oauth.OAuthProvider
tokenValidator *auth.TokenValidator
httpClient *http.Client
compiledRewriteMatch *regexp.Regexp
loadBalancer loadbalancer.LoadBalancer
provider oauth.OAuthProvider
tokenValidator *auth.TokenValidator
}

type LoadBalancerPolicy struct {
Expand Down Expand Up @@ -91,6 +94,12 @@ func (bs *BackendService) GetLoadBalancer() loadbalancer.LoadBalancer {
return bs.loadBalancer
}

// GetCompiledRewriteMatch returns the compiled rewrite match regular expression for the backend service.
func (bs *BackendService) GetCompiledRewriteMatch() *regexp.Regexp {
return bs.compiledRewriteMatch
}


func (bs *BackendService) setLoadBalancer() {
switch bs.LoadBalancerPolicy.Type {
case loadbalancer.Random:
Expand All @@ -108,7 +117,27 @@ func (bs *BackendService) setLoadBalancer() {
}
}

// CompilePath compiles the rewrite match regular expression for the backend service and
// stores it in the compiledRewriteMatch field. If there's an error while compiling,
// the error is returned.
func (bs *BackendService) compilePath() {
if bs.RewriteMatch == "" || bs.RewriteReplace == "" {
return
}

compiled, err := regexp.Compile(bs.RewriteMatch)
if err != nil {
return
}

bs.compiledRewriteMatch = compiled
return
}



func (bs *BackendService) Init() {
bs.setTokenValidator()
bs.setLoadBalancer()
bs.compilePath()
}

0 comments on commit ede404c

Please sign in to comment.