Repository: caddyserver/caddy
File: modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go (Go)

Code before:
				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.orig_uri.path}/"}},
		}
		redirRoute := caddyhttp.Route{
			MatcherSetsRaw: []caddy.ModuleMap{redirMatcherSet},
			HandlersRaw:    []json.RawMessage{caddyconfig.JSONModuleObject(redirHandler, "handler", "static_response", nil)},
		}

		// if tryFiles wasn't overridden, use a reasonable default
		if len(tryFiles) == 0 {
			tryFiles = []string{"{http.request.uri.path}", "{http.request.uri.path}/" + indexFile, indexFile}
		}

		// route to rewrite to PHP index file
		rewriteMatcherSet := caddy.ModuleMap{
			"file": h.JSON(fileserver.MatchFile{
				TryFiles:  tryFiles,
				TryPolicy: "first_exist_fallback",
				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(pathList),
	}

	// create the reverse proxy handler which uses our FastCGI transport

Review comment (suggestion):
This could be risky if users configure their own `try_files` with a different last item. I think we should set `first_exist_fallback` only if the last item ends with `.php` maybe.

Code after:
		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 = ""
			}

			for _, tf := range tryFiles {
				if tf == dirIndex {
					dirRedir = true

					break
				}
			}
		}

		if dirRedir {
			// route to redirect to canonical path if index PHP file
			redirMatcherSet := caddy.ModuleMap{
				"file": h.JSON(fileserver.MatchFile{
					TryFiles: []string{dirIndex},
				}),
				"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.orig_uri.path}/"}},
			}
			redirRoute := caddyhttp.Route{
				MatcherSetsRaw: []caddy.ModuleMap{redirMatcherSet},
				HandlersRaw:    []json.RawMessage{caddyconfig.JSONModuleObject(redirHandler, "handler", "static_response", nil)},
			}

			routes = append(routes, redirRoute)
		}

		// route to rewrite to PHP index file
		rewriteMatcherSet := caddy.ModuleMap{
			"file": h.JSON(fileserver.MatchFile{
				TryFiles:  tryFiles,
				TryPolicy: tryPolicy,
				SplitPath: extensions,
			}),