summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancis Lavoie <lavofr@gmail.com>2020-05-18 14:15:38 -0400
committerGitHub <noreply@github.com>2020-05-18 12:15:38 -0600
commit7243454a96d6dcbe504af7287de1e68ab4b80c83 (patch)
treea838eee179b2cf4a5db45d9a35b3b65de4265d45
parent3fb2c394d130318b893509389f49554067dcdfec (diff)
fastcgi: `php_fastcgi` subdirectives to override shortcut behaviour (#3255)
* fastcgi: Add new php_fastcgi subdirectives to override the shortcut * fastcgi: Support "index off" to disable redir and try_files * fastcgi: Remove whitespace to satisfy linter * fastcgi: Run gofmt * fastcgi: Make a new dispenser instead of using rewind * fastcgi: Some fmt * fastcgi: Add a couple adapt tests * fastcgi: Clean up for loops * fastcgi: Move adapt tests to separate files
-rw-r--r--caddytest/integration/caddyfile_adapt/php_fastcgi_index_off.txt66
-rw-r--r--caddytest/integration/caddyfile_adapt/php_fastcgi_subdirectives.txt118
-rw-r--r--modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go161
3 files changed, 306 insertions, 39 deletions
diff --git a/caddytest/integration/caddyfile_adapt/php_fastcgi_index_off.txt b/caddytest/integration/caddyfile_adapt/php_fastcgi_index_off.txt
new file mode 100644
index 0000000..6d939b4
--- /dev/null
+++ b/caddytest/integration/caddyfile_adapt/php_fastcgi_index_off.txt
@@ -0,0 +1,66 @@
+:8884
+
+php_fastcgi localhost:9000 {
+ # some php_fastcgi-specific subdirectives
+ split .php .php5
+ env VAR1 value1
+ env VAR2 value2
+ root /var/www
+ index off
+
+ # passed through to reverse_proxy (directive order doesn't matter!)
+ lb_policy random
+}
+----------
+{
+ "apps": {
+ "http": {
+ "servers": {
+ "srv0": {
+ "listen": [
+ ":8884"
+ ],
+ "routes": [
+ {
+ "match": [
+ {
+ "path": [
+ "*.php",
+ "*.php5"
+ ]
+ }
+ ],
+ "handle": [
+ {
+ "handler": "reverse_proxy",
+ "load_balancing": {
+ "selection_policy": {
+ "policy": "random"
+ }
+ },
+ "transport": {
+ "env": {
+ "VAR1": "value1",
+ "VAR2": "value2"
+ },
+ "protocol": "fastcgi",
+ "root": "/var/www",
+ "split_path": [
+ ".php",
+ ".php5"
+ ]
+ },
+ "upstreams": [
+ {
+ "dial": "localhost:9000"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/caddytest/integration/caddyfile_adapt/php_fastcgi_subdirectives.txt b/caddytest/integration/caddyfile_adapt/php_fastcgi_subdirectives.txt
new file mode 100644
index 0000000..6733a9e
--- /dev/null
+++ b/caddytest/integration/caddyfile_adapt/php_fastcgi_subdirectives.txt
@@ -0,0 +1,118 @@
+:8884
+
+php_fastcgi localhost:9000 {
+ # some php_fastcgi-specific subdirectives
+ split .php .php5
+ env VAR1 value1
+ env VAR2 value2
+ root /var/www
+ index index.php5
+
+ # passed through to reverse_proxy (directive order doesn't matter!)
+ lb_policy random
+}
+----------
+{
+ "apps": {
+ "http": {
+ "servers": {
+ "srv0": {
+ "listen": [
+ ":8884"
+ ],
+ "routes": [
+ {
+ "match": [
+ {
+ "file": {
+ "try_files": [
+ "{http.request.uri.path}/index.php5"
+ ]
+ },
+ "not": [
+ {
+ "path": [
+ "*/"
+ ]
+ }
+ ]
+ }
+ ],
+ "handle": [
+ {
+ "handler": "static_response",
+ "headers": {
+ "Location": [
+ "{http.request.uri.path}/"
+ ]
+ },
+ "status_code": 308
+ }
+ ]
+ },
+ {
+ "match": [
+ {
+ "file": {
+ "try_files": [
+ "{http.request.uri.path}",
+ "{http.request.uri.path}/index.php5",
+ "index.php5"
+ ],
+ "split_path": [
+ ".php",
+ ".php5"
+ ]
+ }
+ }
+ ],
+ "handle": [
+ {
+ "handler": "rewrite",
+ "uri": "{http.matchers.file.relative}"
+ }
+ ]
+ },
+ {
+ "match": [
+ {
+ "path": [
+ "*.php",
+ "*.php5"
+ ]
+ }
+ ],
+ "handle": [
+ {
+ "handler": "reverse_proxy",
+ "load_balancing": {
+ "selection_policy": {
+ "policy": "random"
+ }
+ },
+ "transport": {
+ "env": {
+ "VAR1": "value1",
+ "VAR2": "value2"
+ },
+ "protocol": "fastcgi",
+ "root": "/var/www",
+ "split_path": [
+ ".php",
+ ".php5"
+ ]
+ },
+ "upstreams": [
+ {
+ "dial": "localhost:9000"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go b/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
index 8a5e27e..7c06adc 100644
--- a/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
+++ b/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
@@ -123,47 +123,133 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
return nil, h.ArgErr()
}
- // route to redirect to canonical path if index PHP file
- redirMatcherSet := caddy.ModuleMap{
- "file": h.JSON(fileserver.MatchFile{
- TryFiles: []string{"{http.request.uri.path}/index.php"},
- }),
- "not": h.JSON(caddyhttp.MatchNot{
- MatcherSetsRaw: []caddy.ModuleMap{
- {
- "path": h.JSON(caddyhttp.MatchPath{"*/"}),
- },
- },
- }),
- }
- redirHandler := caddyhttp.StaticResponse{
- StatusCode: caddyhttp.WeakString(strconv.Itoa(http.StatusPermanentRedirect)),
- Headers: http.Header{"Location": []string{"{http.request.uri.path}/"}},
- }
- redirRoute := caddyhttp.Route{
- MatcherSetsRaw: []caddy.ModuleMap{redirMatcherSet},
- HandlersRaw: []json.RawMessage{caddyconfig.JSONModuleObject(redirHandler, "handler", "static_response", nil)},
- }
+ // set up the transport for FastCGI, and specifically PHP
+ fcgiTransport := Transport{}
- // route to rewrite to PHP index file
- rewriteMatcherSet := caddy.ModuleMap{
- "file": h.JSON(fileserver.MatchFile{
- TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/index.php", "index.php"},
- SplitPath: []string{".php"},
- }),
- }
- rewriteHandler := rewrite.Rewrite{
- URI: "{http.matchers.file.relative}",
+ // set up the set of file extensions allowed to execute PHP code
+ extensions := []string{".php"}
+
+ // set the default index file for the try_files rewrites
+ indexFile := "index.php"
+
+ // make a new dispenser from the remaining tokens so that we
+ // can reset the dispenser back to this point for the
+ // reverse_proxy unmarshaler to read from it as well
+ dispenser := h.NewFromNextSegment()
+
+ // read the subdirectives that we allow as overrides to
+ // the php_fastcgi shortcut
+ // NOTE: we delete the tokens as we go so that the reverse_proxy
+ // unmarshal doesn't see these subdirectives which it cannot handle
+ for dispenser.Next() {
+ for dispenser.NextBlock(0) {
+ switch dispenser.Val() {
+ case "root":
+ if !dispenser.NextArg() {
+ return nil, dispenser.ArgErr()
+ }
+ fcgiTransport.Root = dispenser.Val()
+ dispenser.Delete()
+ dispenser.Delete()
+
+ case "split":
+ extensions = dispenser.RemainingArgs()
+ dispenser.Delete()
+ for range extensions {
+ dispenser.Delete()
+ }
+ if len(extensions) == 0 {
+ return nil, dispenser.ArgErr()
+ }
+
+ case "env":
+ args := dispenser.RemainingArgs()
+ dispenser.Delete()
+ for range args {
+ dispenser.Delete()
+ }
+ if len(args) != 2 {
+ return nil, dispenser.ArgErr()
+ }
+ if fcgiTransport.EnvVars == nil {
+ fcgiTransport.EnvVars = make(map[string]string)
+ }
+ fcgiTransport.EnvVars[args[0]] = args[1]
+
+ case "index":
+ args := dispenser.RemainingArgs()
+ dispenser.Delete()
+ for range args {
+ dispenser.Delete()
+ }
+ if len(args) != 1 {
+ return nil, dispenser.ArgErr()
+ }
+ indexFile = args[0]
+ }
+ }
}
- rewriteRoute := caddyhttp.Route{
- MatcherSetsRaw: []caddy.ModuleMap{rewriteMatcherSet},
- HandlersRaw: []json.RawMessage{caddyconfig.JSONModuleObject(rewriteHandler, "handler", "rewrite", nil)},
+
+ // reset the dispenser after we're done so that the reverse_proxy
+ // unmarshaler can read it from the start
+ dispenser.Reset()
+
+ // set up a route list that we'll append to
+ routes := caddyhttp.RouteList{}
+
+ // set the list of allowed path segments on which to split
+ fcgiTransport.SplitPath = extensions
+
+ // if the index is turned off, we skip the redirect and try_files
+ if indexFile != "off" {
+ // route to redirect to canonical path if index PHP file
+ redirMatcherSet := caddy.ModuleMap{
+ "file": h.JSON(fileserver.MatchFile{
+ TryFiles: []string{"{http.request.uri.path}/" + indexFile},
+ }),
+ "not": h.JSON(caddyhttp.MatchNot{
+ MatcherSetsRaw: []caddy.ModuleMap{
+ {
+ "path": h.JSON(caddyhttp.MatchPath{"*/"}),
+ },
+ },
+ }),
+ }
+ redirHandler := caddyhttp.StaticResponse{
+ StatusCode: caddyhttp.WeakString(strconv.Itoa(http.StatusPermanentRedirect)),
+ Headers: http.Header{"Location": []string{"{http.request.uri.path}/"}},
+ }
+ redirRoute := caddyhttp.Route{
+ MatcherSetsRaw: []caddy.ModuleMap{redirMatcherSet},
+ HandlersRaw: []json.RawMessage{caddyconfig.JSONModuleObject(redirHandler, "handler", "static_response", nil)},
+ }
+
+ // route to rewrite to PHP index file
+ rewriteMatcherSet := caddy.ModuleMap{
+ "file": h.JSON(fileserver.MatchFile{
+ TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/" + indexFile, indexFile},
+ SplitPath: extensions,
+ }),
+ }
+ rewriteHandler := rewrite.Rewrite{
+ URI: "{http.matchers.file.relative}",
+ }
+ rewriteRoute := caddyhttp.Route{
+ MatcherSetsRaw: []caddy.ModuleMap{rewriteMatcherSet},
+ HandlersRaw: []json.RawMessage{caddyconfig.JSONModuleObject(rewriteHandler, "handler", "rewrite", nil)},
+ }
+
+ routes = append(routes, redirRoute, rewriteRoute)
}
// route to actually reverse proxy requests to PHP files;
// match only requests that are for PHP files
+ pathList := []string{}
+ for _, ext := range extensions {
+ pathList = append(pathList, "*"+ext)
+ }
rpMatcherSet := caddy.ModuleMap{
- "path": h.JSON([]string{"*.php"}),
+ "path": h.JSON(pathList),
}
// if the user specified a matcher token, use that
@@ -176,9 +262,6 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
return nil, err
}
- // set up the transport for FastCGI, and specifically PHP
- fcgiTransport := Transport{SplitPath: []string{".php"}}
-
// create the reverse proxy handler which uses our FastCGI transport
rpHandler := &reverseproxy.Handler{
TransportRaw: caddyconfig.JSONModuleObject(fcgiTransport, "protocol", "fastcgi", nil),
@@ -188,7 +271,7 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
// using the reverse_proxy directive syntax
// TODO: this can overwrite our fcgiTransport that we encoded and
// set on the rpHandler... even with a non-fastcgi transport!
- err = rpHandler.UnmarshalCaddyfile(h.Dispenser)
+ err = rpHandler.UnmarshalCaddyfile(dispenser)
if err != nil {
return nil, err
}
@@ -201,7 +284,7 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
}
subroute := caddyhttp.Subroute{
- Routes: caddyhttp.RouteList{redirRoute, rewriteRoute, rpRoute},
+ Routes: append(routes, rpRoute),
}
// the user's matcher is a prerequisite for ours, so