Commit 48d7f1ea authored by Abiola Ibrahim's avatar Abiola Ibrahim

Refactor. Stop useless rewrite if status code is set.

parent be2f5c4b
...@@ -13,6 +13,19 @@ import ( ...@@ -13,6 +13,19 @@ import (
"github.com/mholt/caddy/middleware" "github.com/mholt/caddy/middleware"
) )
// RewriteResult is the result of a rewrite
type RewriteResult int
const (
// RewriteIgnored is returned when rewrite is not done on request.
RewriteIgnored RewriteResult = iota
// RewriteDone is returned when rewrite is done on request.
RewriteDone
// RewriteStatus is returned when rewrite is not needed and status code should be set
// for the request.
RewriteStatus
)
// Rewrite is middleware to rewrite request locations internally before being handled. // Rewrite is middleware to rewrite request locations internally before being handled.
type Rewrite struct { type Rewrite struct {
Next middleware.Handler Next middleware.Handler
...@@ -22,16 +35,18 @@ type Rewrite struct { ...@@ -22,16 +35,18 @@ type Rewrite struct {
// ServeHTTP implements the middleware.Handler interface. // ServeHTTP implements the middleware.Handler interface.
func (rw Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { func (rw Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
outer:
for _, rule := range rw.Rules { for _, rule := range rw.Rules {
if ok := rule.Rewrite(rw.FileSys, r); ok { switch result := rule.Rewrite(rw.FileSys, r); result {
case RewriteDone:
// if rule is complex rule and status code is set break outer
case RewriteIgnored:
break
case RewriteStatus:
// only valid for complex rules.
if cRule, ok := rule.(*ComplexRule); ok && cRule.Status != 0 { if cRule, ok := rule.(*ComplexRule); ok && cRule.Status != 0 {
return cRule.Status, nil return cRule.Status, nil
} }
// rewrite done
break
} }
} }
return rw.Next.ServeHTTP(w, r) return rw.Next.ServeHTTP(w, r)
...@@ -40,7 +55,7 @@ func (rw Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) ...@@ -40,7 +55,7 @@ func (rw Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)
// Rule describes an internal location rewrite rule. // Rule describes an internal location rewrite rule.
type Rule interface { type Rule interface {
// Rewrite rewrites the internal location of the current request. // Rewrite rewrites the internal location of the current request.
Rewrite(http.FileSystem, *http.Request) bool Rewrite(http.FileSystem, *http.Request) RewriteResult
} }
// SimpleRule is a simple rewrite rule. // SimpleRule is a simple rewrite rule.
...@@ -54,7 +69,7 @@ func NewSimpleRule(from, to string) SimpleRule { ...@@ -54,7 +69,7 @@ func NewSimpleRule(from, to string) SimpleRule {
} }
// Rewrite rewrites the internal location of the current request. // Rewrite rewrites the internal location of the current request.
func (s SimpleRule) Rewrite(fs http.FileSystem, r *http.Request) bool { func (s SimpleRule) Rewrite(fs http.FileSystem, r *http.Request) RewriteResult {
if s.From == r.URL.Path { if s.From == r.URL.Path {
// take note of this rewrite for internal use by fastcgi // take note of this rewrite for internal use by fastcgi
// all we need is the URI, not full URL // all we need is the URI, not full URL
...@@ -63,7 +78,7 @@ func (s SimpleRule) Rewrite(fs http.FileSystem, r *http.Request) bool { ...@@ -63,7 +78,7 @@ func (s SimpleRule) Rewrite(fs http.FileSystem, r *http.Request) bool {
// attempt rewrite // attempt rewrite
return To(fs, r, s.To, newReplacer(r)) return To(fs, r, s.To, newReplacer(r))
} }
return false return RewriteIgnored
} }
// ComplexRule is a rewrite rule based on a regular expression // ComplexRule is a rewrite rule based on a regular expression
...@@ -121,33 +136,38 @@ func NewComplexRule(base, pattern, to string, status int, ext []string, ifs []If ...@@ -121,33 +136,38 @@ func NewComplexRule(base, pattern, to string, status int, ext []string, ifs []If
} }
// Rewrite rewrites the internal location of the current request. // Rewrite rewrites the internal location of the current request.
func (r *ComplexRule) Rewrite(fs http.FileSystem, req *http.Request) bool { func (r *ComplexRule) Rewrite(fs http.FileSystem, req *http.Request) (re RewriteResult) {
rPath := req.URL.Path rPath := req.URL.Path
replacer := newReplacer(req) replacer := newReplacer(req)
// validate base // validate base
if !middleware.Path(rPath).Matches(r.Base) { if !middleware.Path(rPath).Matches(r.Base) {
return false return
} }
// validate extensions // if status is present, stop rewrite and return it.
if !r.matchExt(rPath) { if r.Status != 0 {
return false return RewriteStatus
} }
// include trailing slash in regexp if present // validate extensions
start := len(r.Base) if !r.matchExt(rPath) {
if strings.HasSuffix(r.Base, "/") { return
start--
} }
// validate regexp if present // validate regexp if present
if r.Regexp != nil { if r.Regexp != nil {
// include trailing slash in regexp if present
start := len(r.Base)
if strings.HasSuffix(r.Base, "/") {
start--
}
matches := r.FindStringSubmatch(rPath[start:]) matches := r.FindStringSubmatch(rPath[start:])
switch len(matches) { switch len(matches) {
case 0: case 0:
// no match // no match
return false return
default: default:
// set regexp match variables {1}, {2} ... // set regexp match variables {1}, {2} ...
for i := 1; i < len(matches); i++ { for i := 1; i < len(matches); i++ {
...@@ -159,7 +179,7 @@ func (r *ComplexRule) Rewrite(fs http.FileSystem, req *http.Request) bool { ...@@ -159,7 +179,7 @@ func (r *ComplexRule) Rewrite(fs http.FileSystem, req *http.Request) bool {
// validate rewrite conditions // validate rewrite conditions
for _, i := range r.Ifs { for _, i := range r.Ifs {
if !i.True(req) { if !i.True(req) {
return false return
} }
} }
......
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
// To attempts rewrite. It attempts to rewrite to first valid path // To attempts rewrite. It attempts to rewrite to first valid path
// or the last path if none of the paths are valid. // or the last path if none of the paths are valid.
// Returns true if rewrite is successful and false otherwise. // Returns true if rewrite is successful and false otherwise.
func To(fs http.FileSystem, r *http.Request, to string, replacer middleware.Replacer) bool { func To(fs http.FileSystem, r *http.Request, to string, replacer middleware.Replacer) RewriteResult {
tos := strings.Fields(to) tos := strings.Fields(to)
// try each rewrite paths // try each rewrite paths
...@@ -38,7 +38,7 @@ func To(fs http.FileSystem, r *http.Request, to string, replacer middleware.Repl ...@@ -38,7 +38,7 @@ func To(fs http.FileSystem, r *http.Request, to string, replacer middleware.Repl
// Let the user know we got here. Rewrite is expected but // Let the user know we got here. Rewrite is expected but
// the resulting url is invalid. // the resulting url is invalid.
log.Printf("[ERROR] rewrite: resulting path '%v' is invalid. error: %v", t, err) log.Printf("[ERROR] rewrite: resulting path '%v' is invalid. error: %v", t, err)
return false return RewriteIgnored
} }
// take note of this rewrite for internal use by fastcgi // take note of this rewrite for internal use by fastcgi
...@@ -56,7 +56,7 @@ func To(fs http.FileSystem, r *http.Request, to string, replacer middleware.Repl ...@@ -56,7 +56,7 @@ func To(fs http.FileSystem, r *http.Request, to string, replacer middleware.Repl
r.URL.Fragment = u.Fragment r.URL.Fragment = u.Fragment
} }
return true return RewriteDone
} }
// isValidFile checks if file exists on the filesystem. // isValidFile checks if file exists on the filesystem.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment