mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-27 22:23:48 +03:00
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
This commit is contained in:
parent
3fb2c394d1
commit
7243454a96
3 changed files with 306 additions and 39 deletions
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -123,10 +123,89 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||||
return nil, h.ArgErr()
|
return nil, h.ArgErr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set up the transport for FastCGI, and specifically PHP
|
||||||
|
fcgiTransport := Transport{}
|
||||||
|
|
||||||
|
// 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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
// route to redirect to canonical path if index PHP file
|
||||||
redirMatcherSet := caddy.ModuleMap{
|
redirMatcherSet := caddy.ModuleMap{
|
||||||
"file": h.JSON(fileserver.MatchFile{
|
"file": h.JSON(fileserver.MatchFile{
|
||||||
TryFiles: []string{"{http.request.uri.path}/index.php"},
|
TryFiles: []string{"{http.request.uri.path}/" + indexFile},
|
||||||
}),
|
}),
|
||||||
"not": h.JSON(caddyhttp.MatchNot{
|
"not": h.JSON(caddyhttp.MatchNot{
|
||||||
MatcherSetsRaw: []caddy.ModuleMap{
|
MatcherSetsRaw: []caddy.ModuleMap{
|
||||||
|
@ -148,8 +227,8 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||||
// route to rewrite to PHP index file
|
// route to rewrite to PHP index file
|
||||||
rewriteMatcherSet := caddy.ModuleMap{
|
rewriteMatcherSet := caddy.ModuleMap{
|
||||||
"file": h.JSON(fileserver.MatchFile{
|
"file": h.JSON(fileserver.MatchFile{
|
||||||
TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/index.php", "index.php"},
|
TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/" + indexFile, indexFile},
|
||||||
SplitPath: []string{".php"},
|
SplitPath: extensions,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
rewriteHandler := rewrite.Rewrite{
|
rewriteHandler := rewrite.Rewrite{
|
||||||
|
@ -160,10 +239,17 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||||
HandlersRaw: []json.RawMessage{caddyconfig.JSONModuleObject(rewriteHandler, "handler", "rewrite", nil)},
|
HandlersRaw: []json.RawMessage{caddyconfig.JSONModuleObject(rewriteHandler, "handler", "rewrite", nil)},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
routes = append(routes, redirRoute, rewriteRoute)
|
||||||
|
}
|
||||||
|
|
||||||
// route to actually reverse proxy requests to PHP files;
|
// route to actually reverse proxy requests to PHP files;
|
||||||
// match only requests that are for PHP files
|
// match only requests that are for PHP files
|
||||||
|
pathList := []string{}
|
||||||
|
for _, ext := range extensions {
|
||||||
|
pathList = append(pathList, "*"+ext)
|
||||||
|
}
|
||||||
rpMatcherSet := caddy.ModuleMap{
|
rpMatcherSet := caddy.ModuleMap{
|
||||||
"path": h.JSON([]string{"*.php"}),
|
"path": h.JSON(pathList),
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user specified a matcher token, use that
|
// if the user specified a matcher token, use that
|
||||||
|
@ -176,9 +262,6 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||||
return nil, err
|
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
|
// create the reverse proxy handler which uses our FastCGI transport
|
||||||
rpHandler := &reverseproxy.Handler{
|
rpHandler := &reverseproxy.Handler{
|
||||||
TransportRaw: caddyconfig.JSONModuleObject(fcgiTransport, "protocol", "fastcgi", nil),
|
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
|
// using the reverse_proxy directive syntax
|
||||||
// TODO: this can overwrite our fcgiTransport that we encoded and
|
// TODO: this can overwrite our fcgiTransport that we encoded and
|
||||||
// set on the rpHandler... even with a non-fastcgi transport!
|
// set on the rpHandler... even with a non-fastcgi transport!
|
||||||
err = rpHandler.UnmarshalCaddyfile(h.Dispenser)
|
err = rpHandler.UnmarshalCaddyfile(dispenser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -201,7 +284,7 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||||
}
|
}
|
||||||
|
|
||||||
subroute := caddyhttp.Subroute{
|
subroute := caddyhttp.Subroute{
|
||||||
Routes: caddyhttp.RouteList{redirRoute, rewriteRoute, rpRoute},
|
Routes: append(routes, rpRoute),
|
||||||
}
|
}
|
||||||
|
|
||||||
// the user's matcher is a prerequisite for ours, so
|
// the user's matcher is a prerequisite for ours, so
|
||||||
|
|
Loading…
Reference in a new issue