diff --git a/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go b/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go index 03b7226c..8228439f 100644 --- a/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go +++ b/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go @@ -39,6 +39,7 @@ func init() { // root // split // env +// resolve_root_symlink // } // func (t *Transport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { @@ -67,6 +68,9 @@ func (t *Transport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { } t.EnvVars[args[0]] = args[1] + case "resolve_root_symlink": + t.ResolveRootSymlink = true + default: return d.Errf("unrecognized subdirective %s", d.Val()) } @@ -196,6 +200,14 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error return nil, dispenser.ArgErr() } indexFile = args[0] + + case "resolve_root_symlink": + args := dispenser.RemainingArgs() + dispenser.Delete() + for range args { + dispenser.Delete() + } + fcgiTransport.ResolveRootSymlink = true } } } diff --git a/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go b/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go index 8c031724..de6d0a43 100644 --- a/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go +++ b/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go @@ -54,6 +54,14 @@ type Transport struct { // that 404s if the fastcgi path info is not found. SplitPath []string `json:"split_path,omitempty"` + // Path declared as root directory will be resolved to its absolute value + // after the evaluation of any symbolic links. + // Due to the nature of PHP opcache, root directory path is cached: when + // using a symlinked directory as root this could generate errors when + // symlink is changed without php-fpm being restarted; enabling this + // directive will set $_SERVER['DOCUMENT_ROOT'] to the real directory path. + ResolveRootSymlink bool `json:"resolve_root_symlink,omitempty"` + // Extra environment variables. EnvVars map[string]string `json:"env,omitempty"` @@ -179,6 +187,13 @@ func (t Transport) buildEnv(r *http.Request) (map[string]string, error) { return nil, err } + if t.ResolveRootSymlink { + root, err = filepath.EvalSymlinks(root) + if err != nil { + return nil, err + } + } + fpath := r.URL.Path // split "actual path" from "path info" if configured