@marcel91200 / caddy Mirror · read-only / commits / 25dea290
Fork 0

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

http: A little more polish on rewrite handler and try_files directive

Matthew Holt committed Jan 11, 2020 at 13:47 UTC 25dea2903e613534e00a2a4e305e0c8f2daeea8d
5 files changed +51 -48
modules/caddyhttp/fileserver/caddyfile.go
+16 -12
@@ -107,11 +107,17 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
107 // try_files <files...>
108 // }
109 // }
110 -// rewrite @try_files {http.matchers.file.relative}{http.request.uri.query_string}
110 +// rewrite @try_files {http.matchers.file.relative}
111 //
112 -// If any of the files in the list have a query string, the query string will
113 -// be ignored when checking for file existence, but will be augmented into
114 -// the request's URI when rewriting the request.
112 +// This directive rewrites request paths only, preserving any other part
113 +// of the URI, unless the part is explicitly given in the file list. For
114 +// example, if any of the files in the list have a query string:
115 +//
116 +// try_files {path} index.php?{query}&p={path}
117 +//
118 +// then the query string will not be treated as part of the file name; and
119 +// if that file matches, the given query string will replace any query string
120 +// that already exists on the request URI.
121 func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
122 if !h.Next() {
123 return nil, h.ArgErr()
@@ -123,16 +129,14 @@ func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
129 }
130
131 // makeRoute returns a route that tries the files listed in try
126 - // and then rewrites to the matched file, and appends writeURIAppend
127 - // to the end of the query string.
128 - makeRoute := func(try []string, writeURIAppend string) []httpcaddyfile.ConfigValue {
132 + // and then rewrites to the matched file; userQueryString is
133 + // appended to the rewrite rule.
134 + makeRoute := func(try []string, userQueryString string) []httpcaddyfile.ConfigValue {
135 handler := rewrite.Rewrite{
130 - URI: "{http.matchers.file.relative}{http.request.uri.query_string}" + writeURIAppend,
136 + URI: "{http.matchers.file.relative}" + userQueryString,
137 }
138 matcherSet := caddy.ModuleMap{
133 - "file": h.JSON(MatchFile{
134 - TryFiles: try,
135 - }),
139 + "file": h.JSON(MatchFile{TryFiles: try}),
140 }
141 return h.NewRoute(matcherSet, handler)
142 }
@@ -149,7 +153,7 @@ func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
153 result = append(result, makeRoute(try, "")...)
154 try = []string{}
155 }
152 - result = append(result, makeRoute([]string{item[:idx]}, "&"+item[idx+1:])...)
156 + result = append(result, makeRoute([]string{item[:idx]}, item[idx:])...)
157 continue
158 }
159 // accumulate consecutive non-query-string parameters
modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
+1 -1
@@ -149,7 +149,7 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
149 }),
150 }
151 rewriteHandler := rewrite.Rewrite{
152 - URI: "{http.matchers.file.relative}?{http.request.uri.query}",
152 + URI: "{http.matchers.file.relative}",
153 }
154 rewriteRoute := caddyhttp.Route{
155 MatcherSetsRaw: []caddy.ModuleMap{rewriteMatcherSet},
modules/caddyhttp/rewrite/caddyfile.go
+4 -3
@@ -32,7 +32,8 @@ func init() {
32 //
33 // rewrite [<matcher>] <to>
34 //
35 -// The <to> parameter becomes the new URI.
35 +// Only URI components which are given in <to> will be set in the resulting URI.
36 +// See the docs for the rewrite handler for more information.
37 func parseCaddyfileRewrite(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
38 var rewr Rewrite
39 for h.Next() {
@@ -58,7 +59,7 @@ func parseCaddyfileStripPrefix(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHand
59 if !h.NextArg() {
60 return nil, h.ArgErr()
61 }
61 - rewr.StripPrefix = h.Val()
62 + rewr.StripPathPrefix = h.Val()
63 if h.NextArg() {
64 return nil, h.ArgErr()
65 }
@@ -77,7 +78,7 @@ func parseCaddyfileStripSuffix(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHand
78 if !h.NextArg() {
79 return nil, h.ArgErr()
80 }
80 - rewr.StripSuffix = h.Val()
81 + rewr.StripPathSuffix = h.Val()
82 if h.NextArg() {
83 return nil, h.ArgErr()
84 }
modules/caddyhttp/rewrite/rewrite.go
+24 -26
@@ -17,7 +17,6 @@ package rewrite
17 import (
18 "net/http"
19 "net/url"
20 - "strconv"
20 "strings"
21
22 "github.com/caddyserver/caddy/v2"
@@ -31,32 +30,40 @@ func init() {
30
31 // Rewrite is a middleware which can rewrite HTTP requests.
32 //
34 -// These rewrite properties are applied to a request in this order:
35 -// Method, URI, StripPrefix, StripSuffix, URISubstring.
36 -//
37 -// TODO: This module is still a WIP and may experience breaking changes.
33 +// The Method and URI properties are "setters": the request URI
34 +// will be set to the given values. Other properties are "modifiers":
35 +// they modify existing files but do not explicitly specify what the
36 +// result will be. It is atypical to combine the use of setters and
37 +// modifiers in a single rewrite.
38 type Rewrite struct {
39 // Changes the request's HTTP verb.
40 Method string `json:"method,omitempty"`
41
42 - // Changes the request's URI (path, query string, and fragment if present).
42 + // Changes the request's URI, which consists of path and query string.
43 // Only components of the URI that are specified will be changed.
44 + // For example, a value of "/foo.html" or "foo.html" will only change
45 + // the path and will preserve any existing query string. Similarly, a
46 + // value of "?a=b" will only change the query string and will not affect
47 + // the path. Both can also be changed: "/foo?a=b" - this sets both the
48 + // path and query string at the same time.
49 + //
50 + // You can also use placeholders. For example, to preserve the existing
51 + // query string, you might use: "?{http.request.uri.query}&a=b". Any
52 + // key-value pairs you add to the query string will not overwrite
53 + // existing values.
54 + //
55 + // To clear the query string, explicitly set an empty one: "?"
56 URI string `json:"uri,omitempty"`
57
58 // Strips the given prefix from the beginning of the URI path.
47 - StripPrefix string `json:"strip_prefix,omitempty"`
59 + StripPathPrefix string `json:"strip_path_prefix,omitempty"`
60
61 // Strips the given suffix from the end of the URI path.
50 - StripSuffix string `json:"strip_suffix,omitempty"`
62 + StripPathSuffix string `json:"strip_path_suffix,omitempty"`
63
64 // Performs substring replacements on the URI.
65 URISubstring []replacer `json:"uri_substring,omitempty"`
66
55 - // If set to a 3xx HTTP status code and if the URI was rewritten (changed),
56 - // the handler will issue a simple HTTP redirect to the new URI using the
57 - // given status code.
58 - HTTPRedirect caddyhttp.WeakString `json:"http_redirect,omitempty"`
59 -
67 logger *zap.Logger
68 }
69
@@ -88,15 +95,6 @@ func (rewr Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddy
95 zap.String("method", r.Method),
96 zap.String("uri", r.RequestURI),
97 )
91 - if rewr.HTTPRedirect != "" {
92 - statusCode, err := strconv.Atoi(repl.ReplaceAll(rewr.HTTPRedirect.String(), ""))
93 - if err != nil {
94 - return caddyhttp.Error(http.StatusInternalServerError, err)
95 - }
96 - w.Header().Set("Location", r.RequestURI)
97 - w.WriteHeader(statusCode)
98 - return nil
99 - }
98 }
99
100 return next.ServeHTTP(w, r)
@@ -148,12 +146,12 @@ func (rewr Rewrite) rewrite(r *http.Request, repl *caddy.Replacer, logger *zap.L
146 }
147
148 // strip path prefix or suffix
151 - if rewr.StripPrefix != "" {
152 - prefix := repl.ReplaceAll(rewr.StripPrefix, "")
149 + if rewr.StripPathPrefix != "" {
150 + prefix := repl.ReplaceAll(rewr.StripPathPrefix, "")
151 r.URL.Path = strings.TrimPrefix(r.URL.Path, prefix)
152 }
155 - if rewr.StripSuffix != "" {
156 - suffix := repl.ReplaceAll(rewr.StripSuffix, "")
153 + if rewr.StripPathSuffix != "" {
154 + suffix := repl.ReplaceAll(rewr.StripPathSuffix, "")
155 r.URL.Path = strings.TrimSuffix(r.URL.Path, suffix)
156 }
157
modules/caddyhttp/rewrite/rewrite_test.go
+6 -6
@@ -150,33 +150,33 @@ func TestRewrite(t *testing.T) {
150 },
151
152 {
153 - rule: Rewrite{StripPrefix: "/prefix"},
153 + rule: Rewrite{StripPathPrefix: "/prefix"},
154 input: newRequest(t, "GET", "/foo/bar"),
155 expect: newRequest(t, "GET", "/foo/bar"),
156 },
157 {
158 - rule: Rewrite{StripPrefix: "/prefix"},
158 + rule: Rewrite{StripPathPrefix: "/prefix"},
159 input: newRequest(t, "GET", "/prefix/foo/bar"),
160 expect: newRequest(t, "GET", "/foo/bar"),
161 },
162 {
163 - rule: Rewrite{StripPrefix: "/prefix"},
163 + rule: Rewrite{StripPathPrefix: "/prefix"},
164 input: newRequest(t, "GET", "/foo/prefix/bar"),
165 expect: newRequest(t, "GET", "/foo/prefix/bar"),
166 },
167
168 {
169 - rule: Rewrite{StripSuffix: "/suffix"},
169 + rule: Rewrite{StripPathSuffix: "/suffix"},
170 input: newRequest(t, "GET", "/foo/bar"),
171 expect: newRequest(t, "GET", "/foo/bar"),
172 },
173 {
174 - rule: Rewrite{StripSuffix: "suffix"},
174 + rule: Rewrite{StripPathSuffix: "suffix"},
175 input: newRequest(t, "GET", "/foo/bar/suffix"),
176 expect: newRequest(t, "GET", "/foo/bar/"),
177 },
178 {
179 - rule: Rewrite{StripSuffix: "/suffix"},
179 + rule: Rewrite{StripPathSuffix: "/suffix"},
180 input: newRequest(t, "GET", "/foo/suffix/bar"),
181 expect: newRequest(t, "GET", "/foo/suffix/bar"),
182 },