@marcel91200 / caddy Mirror · read-only / commits / 5e9d81b5
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

try_files, rewrite: allow query string in try_files (fix #2891)

Also some minor cleanup/improvements discovered along the way

Matthew Holt committed Dec 12, 2019 at 15:27 UTC 5e9d81b507e0beb46b3812e21566bfef79c87af4
4 files changed +57 -23
caddyconfig/httpcaddyfile/directives.go
+10 -3
@@ -53,6 +53,8 @@ func RegisterDirective(dir string, setupFunc UnmarshalFunc) {
53
54 // RegisterHandlerDirective is like RegisterDirective, but for
55 // directives which specifically output only an HTTP handler.
56 +// Directives registered with this function will always have
57 +// an optional matcher token as the first argument.
58 func RegisterHandlerDirective(dir string, setupFunc UnmarshalHandlerFunc) {
59 RegisterDirective(dir, func(h Helper) ([]ConfigValue, error) {
60 if !h.Next() {
@@ -117,7 +119,7 @@ func (h Helper) Caddyfiles() []string {
119 }
120
121 // JSON converts val into JSON. Any errors are added to warnings.
120 -func (h Helper) JSON(val interface{}, warnings *[]caddyconfig.Warning) json.RawMessage {
122 +func (h Helper) JSON(val interface{}) json.RawMessage {
123 return caddyconfig.JSON(val, h.warnings)
124 }
125
@@ -135,9 +137,14 @@ func (h Helper) MatcherToken() (caddy.ModuleMap, bool, error) {
137 // NewRoute returns config values relevant to creating a new HTTP route.
138 func (h Helper) NewRoute(matcherSet caddy.ModuleMap,
139 handler caddyhttp.MiddlewareHandler) []ConfigValue {
138 - mod, err := caddy.GetModule(caddy.GetModuleName(handler))
140 + mod, err := caddy.GetModule(caddy.GetModuleID(handler))
141 if err != nil {
140 - // TODO: append to warnings
142 + *h.warnings = append(*h.warnings, caddyconfig.Warning{
143 + File: h.File(),
144 + Line: h.Line(),
145 + Message: err.Error(),
146 + })
147 + return nil
148 }
149 var matcherSetsRaw []caddy.ModuleMap
150 if matcherSet != nil {
modules/caddyhttp/fileserver/caddyfile.go
+42 -10
@@ -15,6 +15,8 @@
15 package fileserver
16
17 import (
18 + "strings"
19 +
20 "github.com/caddyserver/caddy/v2"
21 "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
22 "github.com/caddyserver/caddy/v2/modules/caddyhttp"
@@ -98,7 +100,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
100 //
101 // try_files <files...>
102 //
101 -// and is shorthand for:
103 +// and is basically shorthand for:
104 //
105 // matcher:try_files {
106 // file {
@@ -107,25 +109,55 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
109 // }
110 // rewrite match:try_files {http.matchers.file.relative}{http.request.uri.query_string}
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.
115 func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
116 if !h.Next() {
117 return nil, h.ArgErr()
118 }
119
115 - try := h.RemainingArgs()
116 - if len(try) == 0 {
120 + tryFiles := h.RemainingArgs()
121 + if len(tryFiles) == 0 {
122 return nil, h.ArgErr()
123 }
124
120 - handler := rewrite.Rewrite{
121 - URI: "{http.matchers.file.relative}{http.request.uri.query_string}",
125 + // 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 {
129 + handler := rewrite.Rewrite{
130 + URI: "{http.matchers.file.relative}{http.request.uri.query_string}" + writeURIAppend,
131 + }
132 + matcherSet := caddy.ModuleMap{
133 + "file": h.JSON(MatchFile{
134 + TryFiles: try,
135 + }),
136 + }
137 + return h.NewRoute(matcherSet, handler)
138 }
139
124 - matcherSet := caddy.ModuleMap{
125 - "file": h.JSON(MatchFile{
126 - TryFiles: try,
127 - }, nil),
140 + var result []httpcaddyfile.ConfigValue
141 +
142 + // if there are query strings in the list, we have to split into
143 + // a separate route for each item with a query string, because
144 + // the rewrite is different for that item
145 + var try []string
146 + for _, item := range tryFiles {
147 + if idx := strings.Index(item, "?"); idx >= 0 {
148 + if len(try) > 0 {
149 + result = append(result, makeRoute(try, "")...)
150 + try = []string{}
151 + }
152 + result = append(result, makeRoute([]string{item[:idx]}, "&"+item[idx+1:])...)
153 + continue
154 + }
155 + // accumulate consecutive non-query-string parameters
156 + try = append(try, item)
157 + }
158 + if len(try) > 0 {
159 + result = append(result, makeRoute(try, "")...)
160 }
161
130 - return h.NewRoute(matcherSet, handler), nil
162 + return result, nil
163 }
modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
+5 -5
@@ -125,12 +125,12 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
125 redirMatcherSet := caddy.ModuleMap{
126 "file": h.JSON(fileserver.MatchFile{
127 TryFiles: []string{"{http.request.uri.path}/index.php"},
128 - }, nil),
128 + }),
129 "not": h.JSON(caddyhttp.MatchNegate{
130 MatchersRaw: caddy.ModuleMap{
131 - "path": h.JSON(caddyhttp.MatchPath{"*/"}, nil),
131 + "path": h.JSON(caddyhttp.MatchPath{"*/"}),
132 },
133 - }, nil),
133 + }),
134 }
135 redirHandler := caddyhttp.StaticResponse{
136 StatusCode: caddyhttp.WeakString("308"),
@@ -145,7 +145,7 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
145 rewriteMatcherSet := caddy.ModuleMap{
146 "file": h.JSON(fileserver.MatchFile{
147 TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/index.php", "index.php"},
148 - }, nil),
148 + }),
149 }
150 rewriteHandler := rewrite.Rewrite{
151 URI: "{http.matchers.file.relative}{http.request.uri.query_string}",
@@ -159,7 +159,7 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
159 // route to actually reverse proxy requests to PHP files;
160 // match only requests that are for PHP files
161 rpMatcherSet := caddy.ModuleMap{
162 - "path": h.JSON([]string{"*.php"}, nil),
162 + "path": h.JSON([]string{"*.php"}),
163 }
164
165 // if the user specified a matcher token, use that
modules/caddyhttp/rewrite/rewrite.go
-5
@@ -190,11 +190,6 @@ func (rep replacer) do(r *http.Request, repl caddy.Replacer) bool {
190 r.URL.Path = strings.Replace(oldPath, find, replace, lim)
191 r.URL.RawQuery = strings.Replace(oldQuery, find, replace, lim)
192
193 - // changed := r.URL.Path != oldPath && r.URL.RawQuery != oldQuery
194 - // if changed {
195 - // r.RequestURI = r.URL.RequestURI()
196 - // }
197 -
193 return r.URL.Path != oldPath && r.URL.RawQuery != oldQuery
194 }
195