Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 14, 05:15 UTC
rewrite: Options to strip prefix/suffix and issue redirects
Fixes #2011
Matthew Holt committed
Oct 19, 2019 at 19:22 UTC
208f2ff93c1bd2c009e4b96f664c1808ede79f3a
1 file changed
+54
-7
modules/caddyhttp/rewrite/rewrite.go
+54
-7
@@ -15,8 +15,10 @@
15
package rewrite
16
17
import (
18
+ "fmt"
19
"net/http"
20
"net/url"
21
+ "strconv"
22
"strings"
23
24
"github.com/caddyserver/caddy/v2"
@@ -29,9 +31,14 @@ func init() {
31
32
// Rewrite is a middleware which can rewrite HTTP requests.
33
type Rewrite struct {
32
- Method string `json:"method,omitempty"`
33
- URI string `json:"uri,omitempty"`
34
- Rehandle bool `json:"rehandle,omitempty"`
34
+ Method string `json:"method,omitempty"`
35
+ URI string `json:"uri,omitempty"`
36
+
37
+ StripPathPrefix string `json:"strip_path_prefix,omitempty"`
38
+ StripPathSuffix string `json:"strip_path_suffix,omitempty"`
39
+
40
+ HTTPRedirect caddyhttp.WeakString `json:"http_redirect,omitempty"`
41
+ Rehandle bool `json:"rehandle,omitempty"`
42
}
43
44
// CaddyModule returns the Caddy module information.
@@ -42,18 +49,28 @@ func (Rewrite) CaddyModule() caddy.ModuleInfo {
49
}
50
}
51
52
+// Validate ensures rewr's configuration is valid.
53
+func (rewr Rewrite) Validate() error {
54
+ if rewr.HTTPRedirect != "" && rewr.Rehandle {
55
+ return fmt.Errorf("cannot be configured to both write a redirect response and rehandle internally")
56
+ }
57
+ return nil
58
+}
59
+
60
func (rewr Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
61
repl := r.Context().Value(caddy.ReplacerCtxKey).(caddy.Replacer)
47
- var rehandleNeeded bool
62
+ var changed bool
63
64
+ // rewrite the method
65
if rewr.Method != "" {
66
method := r.Method
67
r.Method = strings.ToUpper(repl.ReplaceAll(rewr.Method, ""))
68
if r.Method != method {
53
- rehandleNeeded = true
69
+ changed = true
70
}
71
}
72
73
+ // rewrite the URI
74
if rewr.URI != "" {
75
oldURI := r.RequestURI
76
newURI := repl.ReplaceAll(rewr.URI, "")
@@ -73,14 +90,44 @@ func (rewr Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddy
90
}
91
92
if newURI != oldURI {
76
- rehandleNeeded = true
93
+ changed = true
94
}
95
}
96
80
- if rehandleNeeded && rewr.Rehandle {
97
+ // strip path prefix or suffix
98
+ if rewr.StripPathPrefix != "" {
99
+ prefix := repl.ReplaceAll(rewr.StripPathPrefix, "")
100
+ r.URL.Path = strings.TrimPrefix(r.URL.Path, prefix)
101
+ newURI := r.URL.String()
102
+ if newURI != r.RequestURI {
103
+ changed = true
104
+ }
105
+ r.RequestURI = newURI
106
+ }
107
+ if rewr.StripPathSuffix != "" {
108
+ suffix := repl.ReplaceAll(rewr.StripPathSuffix, "")
109
+ r.URL.Path = strings.TrimSuffix(r.URL.Path, suffix)
110
+ newURI := r.URL.String()
111
+ if newURI != r.RequestURI {
112
+ changed = true
113
+ }
114
+ r.RequestURI = newURI
115
+ }
116
+
117
+ if changed && rewr.Rehandle {
118
return caddyhttp.ErrRehandle
119
}
120
121
+ if changed && rewr.HTTPRedirect != "" {
122
+ statusCode, err := strconv.Atoi(repl.ReplaceAll(rewr.HTTPRedirect.String(), ""))
123
+ if err != nil {
124
+ return caddyhttp.Error(http.StatusInternalServerError, err)
125
+ }
126
+ w.Header().Set("Location", r.RequestURI)
127
+ w.WriteHeader(statusCode)
128
+ return nil
129
+ }
130
+
131
return next.ServeHTTP(w, r)
132
}
133