diff options
author | Matthew Holt <mholt@users.noreply.github.com> | 2019-10-19 19:22:29 -0600 |
---|---|---|
committer | Matthew Holt <mholt@users.noreply.github.com> | 2019-10-19 19:22:29 -0600 |
commit | 208f2ff93c1bd2c009e4b96f664c1808ede79f3a (patch) | |
tree | 072a5fc3f1624cd8dbd4a8d85d7ec2ff4b83dd60 /modules | |
parent | 19e834cf36ed757738ff7504eb8b3fff45f67a79 (diff) |
rewrite: Options to strip prefix/suffix and issue redirects
Fixes #2011
Diffstat (limited to 'modules')
-rw-r--r-- | modules/caddyhttp/rewrite/rewrite.go | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/modules/caddyhttp/rewrite/rewrite.go b/modules/caddyhttp/rewrite/rewrite.go index f434a38..7d4c6f7 100644 --- a/modules/caddyhttp/rewrite/rewrite.go +++ b/modules/caddyhttp/rewrite/rewrite.go @@ -15,8 +15,10 @@ package rewrite import ( + "fmt" "net/http" "net/url" + "strconv" "strings" "github.com/caddyserver/caddy/v2" @@ -29,9 +31,14 @@ func init() { // Rewrite is a middleware which can rewrite HTTP requests. type Rewrite struct { - Method string `json:"method,omitempty"` - URI string `json:"uri,omitempty"` - Rehandle bool `json:"rehandle,omitempty"` + Method string `json:"method,omitempty"` + URI string `json:"uri,omitempty"` + + StripPathPrefix string `json:"strip_path_prefix,omitempty"` + StripPathSuffix string `json:"strip_path_suffix,omitempty"` + + HTTPRedirect caddyhttp.WeakString `json:"http_redirect,omitempty"` + Rehandle bool `json:"rehandle,omitempty"` } // CaddyModule returns the Caddy module information. @@ -42,18 +49,28 @@ func (Rewrite) CaddyModule() caddy.ModuleInfo { } } +// Validate ensures rewr's configuration is valid. +func (rewr Rewrite) Validate() error { + if rewr.HTTPRedirect != "" && rewr.Rehandle { + return fmt.Errorf("cannot be configured to both write a redirect response and rehandle internally") + } + return nil +} + func (rewr Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { repl := r.Context().Value(caddy.ReplacerCtxKey).(caddy.Replacer) - var rehandleNeeded bool + var changed bool + // rewrite the method if rewr.Method != "" { method := r.Method r.Method = strings.ToUpper(repl.ReplaceAll(rewr.Method, "")) if r.Method != method { - rehandleNeeded = true + changed = true } } + // rewrite the URI if rewr.URI != "" { oldURI := r.RequestURI newURI := repl.ReplaceAll(rewr.URI, "") @@ -73,14 +90,44 @@ func (rewr Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddy } if newURI != oldURI { - rehandleNeeded = true + changed = true } } - if rehandleNeeded && rewr.Rehandle { + // strip path prefix or suffix + if rewr.StripPathPrefix != "" { + prefix := repl.ReplaceAll(rewr.StripPathPrefix, "") + r.URL.Path = strings.TrimPrefix(r.URL.Path, prefix) + newURI := r.URL.String() + if newURI != r.RequestURI { + changed = true + } + r.RequestURI = newURI + } + if rewr.StripPathSuffix != "" { + suffix := repl.ReplaceAll(rewr.StripPathSuffix, "") + r.URL.Path = strings.TrimSuffix(r.URL.Path, suffix) + newURI := r.URL.String() + if newURI != r.RequestURI { + changed = true + } + r.RequestURI = newURI + } + + if changed && rewr.Rehandle { return caddyhttp.ErrRehandle } + if changed && rewr.HTTPRedirect != "" { + statusCode, err := strconv.Atoi(repl.ReplaceAll(rewr.HTTPRedirect.String(), "")) + if err != nil { + return caddyhttp.Error(http.StatusInternalServerError, err) + } + w.Header().Set("Location", r.RequestURI) + w.WriteHeader(statusCode) + return nil + } + return next.ServeHTTP(w, r) } |