mirror of
https://github.com/caddyserver/caddy.git
synced 2026-11-11 19:37:55 +00:00
fastcgi: rewrite to index.php only if it exists (#8372)
php_fastcgi used first_exist_fallback, which since v2.11.8 matches its final entry even when the file is absent. On a site without index.php, "/", directories with an index.html and missing files were all rewritten to the missing index.php, so file_server never served them. php_fastcgi now uses first_exist, as v2.11.7 effectively did since globbing skipped absent files. Explicitly configured first_exist_fallback keeps its semantics. The transport normalizes the path itself, so the dot-segment protection doesn't depend on this rewrite. Fixes #8367
This commit is contained in:
1 parent
b30c019341
commit
8822b60863
6 files changed
+52
-15
No files matched your search
@@ -58,7 +58,6 @@
|
||||
"{http.request.uri.path}/index.php",
|
||||
"index.php"
|
||||
],
|
||||
"try_policy": "first_exist_fallback",
|
||||
"split_path": [
|
||||
".php"
|
||||
]
|
||||
|
||||
@@ -73,8 +73,7 @@ php_fastcgi @test localhost:9000
|
||||
"{http.request.uri.path}",
|
||||
"{http.request.uri.path}/index.php",
|
||||
"index.php"
|
||||
],
|
||||
"try_policy": "first_exist_fallback"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -59,7 +59,6 @@ php_fastcgi localhost:9000 {
|
||||
"{http.request.uri.path}/index.php5",
|
||||
"index.php5"
|
||||
],
|
||||
"try_policy": "first_exist_fallback",
|
||||
"split_path": [
|
||||
".php",
|
||||
".php5"
|
||||
|
||||
-1
@@ -32,7 +32,6 @@ php_fastcgi localhost:9000 {
|
||||
"{http.request.uri.path}",
|
||||
"index.php"
|
||||
],
|
||||
"try_policy": "first_exist_fallback",
|
||||
"split_path": [
|
||||
".php",
|
||||
".php5"
|
||||
|
||||
@@ -227,3 +227,53 @@ func TestPHPFastCGIDirectoryRedirectStaysOnOrigin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Without a PHP front controller, php_fastcgi must leave static files and
|
||||
// directory indexes to file_server instead of sending them to a missing
|
||||
// index.php (https://github.com/caddyserver/caddy/issues/8367).
|
||||
func TestPHPFastCGIWithoutIndexPHP(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
for name, content := range map[string]string{
|
||||
"index.html": "home",
|
||||
"style.css": "css",
|
||||
"about/index.html": "about",
|
||||
} {
|
||||
file := filepath.Join(root, filepath.FromSlash(name))
|
||||
if err := os.MkdirAll(filepath.Dir(file), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(file, []byte(content), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
backend := startFakePHPFPM(t)
|
||||
|
||||
tester := caddytest.NewTester(t)
|
||||
tester.InitServer(fmt.Sprintf(`{
|
||||
skip_install_trust
|
||||
admin localhost:2999
|
||||
http_port 9080
|
||||
https_port 9443
|
||||
grace_period 1ns
|
||||
}
|
||||
|
||||
localhost:9080 {
|
||||
root * %s
|
||||
php_fastcgi %s
|
||||
file_server
|
||||
}
|
||||
`, root, backend), "caddyfile")
|
||||
|
||||
tester.AssertGetResponse("http://localhost:9080/", http.StatusOK, "home")
|
||||
tester.AssertGetResponse("http://localhost:9080/about/", http.StatusOK, "about")
|
||||
tester.AssertGetResponse("http://localhost:9080/style.css", http.StatusOK, "css")
|
||||
tester.AssertGetResponse("http://localhost:9080/missing", http.StatusNotFound, "")
|
||||
|
||||
// a front controller added later handles the paths that match no file
|
||||
if err := os.WriteFile(filepath.Join(root, "index.php"), []byte("<?php // front controller"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tester.AssertGetResponse("http://localhost:9080/missing", http.StatusOK, "SCRIPT_FILENAME="+filepath.Join(root, "index.php"))
|
||||
tester.AssertGetResponse("http://localhost:9080/style.css", http.StatusOK, "css")
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig"
|
||||
@@ -140,10 +139,9 @@ func (t *Transport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||
// }
|
||||
// redir @canonicalPath {path}/ 308
|
||||
//
|
||||
// # If the requested file does not exist, try index files and assume index.php always exists
|
||||
// # If the requested file does not exist, try index files
|
||||
// @indexFiles file {
|
||||
// try_files {path} {path}/index.php index.php
|
||||
// try_policy first_exist_fallback
|
||||
// split_path .php
|
||||
// }
|
||||
// rewrite @indexFiles {http.matchers.file.relative}
|
||||
@@ -317,18 +315,12 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||
if indexFile != "off" {
|
||||
var dirRedir bool
|
||||
dirIndex := "{http.request.uri.path}/" + indexFile
|
||||
tryPolicy := "first_exist_fallback"
|
||||
|
||||
// if tryFiles wasn't overridden, use a reasonable default
|
||||
if len(tryFiles) == 0 {
|
||||
tryFiles = []string{"{http.request.uri.path}", dirIndex, indexFile}
|
||||
dirRedir = true
|
||||
} else {
|
||||
if !strings.HasSuffix(tryFiles[len(tryFiles)-1], ".php") {
|
||||
// use first_exist strategy if the last file is not a PHP file
|
||||
tryPolicy = ""
|
||||
}
|
||||
|
||||
dirRedir = slices.Contains(tryFiles, dirIndex)
|
||||
}
|
||||
|
||||
@@ -370,7 +362,6 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||
rewriteMatcherSet := caddy.ModuleMap{
|
||||
"file": h.JSON(fileserver.MatchFile{
|
||||
TryFiles: tryFiles,
|
||||
TryPolicy: tryPolicy,
|
||||
SplitPath: extensions,
|
||||
}),
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user