子目录中的 FallbackResource

子目录中的 FallbackResource

我使用以下工具管理大量 PHP 应用程序前端控制器s 和以下 htaccess 文件:

FallbackResource /index.php

是的,这是整个文件(针对每个应用程序)!

但是,一些网站位于子文件夹中,因此需要进行以下更改:

FallbackResource /subfolder/index.php

你可能已经猜到了,/开头的表示路径是相对于站点/虚拟主机的,而这里的路径需要相对于目录的。

(如果我使用mod_rewrite而不是mod_dir,我将必须RewriteBase以类似的方式根据需要向每个子目录添加。)

我认为我可以通过以下方式解决这个问题:

FallbackResource index.php # No slash!

但是,当站点的重写包含斜杠时,例如,如果应用程序是,/store/而其中的路径是products/1234,那么 Apache 会查找/store/products/index.php而不是,/store/index.php并返回 500,并在日志中包含以下消息:

由于可能的配置错误,请求超出了 10 个子请求嵌套级别的限制。如有必要,请使用“LimitInternalRecursion”增加限制。使用“LogLevel debug”获取回溯。

我原以为该FallbackResource路径是相对于配置它的 .htaccess 文件而言的,但看起来它实际上是相对于请求的 URL 而言的。

有没有办法可以按照FallbackResource我预期的方式行事?


如果这是答案,我可以按原样使用它,但如果可以做到这一点,管理我拥有的网站将变得容易得多。这些网站使用相同的基本代码,但主题和数据库连接不同,现在的工作方式是每次部署新版本的代码时我都必须修改 htaccess 文件(因为它已签入 Git)。如果我们可以做到不必每次都记得进行此修改,那就太好了。

答案1

我认为这并非易事。我尝试在主配置文件中使用这两个指令中较新的变量插值来组合DirectoryMatch和。LocationMatch

尽管类似这样的FallBackResource index.html配置是完全有效的,但我与 Michael Hampton 一样担心,任何使用相对 URL 都可能导致问题。对于FallBackResource index.html特定目录树,index.html 必须总是存在,否则您将获得针对index.html无法找到的请求描述的递归循环。

就您而言,您需要一个带有的顶级.htaccess文件FallBackResource /index.html,然后FallBackResource /subfoldername/index.html位于每个相关的子文件夹中。

生成这些内容的简单脚本可能是最安全的。

答案2

我最初提出该问题的网站已不再存在,但以下是我最终做的事情。

我最终将这些网站移至运行 Nginx 的服务器,其中所有配置均使用try_files指令在服务器的配置文件中完成。这样管理起来容易得多。

答案3

DirectoryIndex我相信使用而不是 的解决方法FallbackResource也可能有效。以下内容将匹配/a/script/文件/some/path/to/a/script/index.pythen /some/path/to/a/script/index.htmlthen/some/path/to/subfolder/index.py和 finally /some/path/index.py。这依赖于DirectoryIndex遵守绝对路径。

ScriptAlias / "/some/path/to/"
<Directory "/some/path/to/">
  Options +ExecCGI
  AddHandler cgi-script .py
  DirectoryIndex index.py index.html 
  # Appending  /index.py seems to work whereas FallbackResource does not
  DirectoryIndex /subfolder/index.py
  DirectoryIndex /index.py
  FallbackResource /index.py
  Require all granted
</Directory>

重复调用将DirectoryIndex附加到先前的调用。在我的情况下FallbackResource不起作用,我偶然发现了一个解决方案。以上适用于 CGI/Python 文件,但我相信它在您的场景中也适用。

答案4

在旁边:使用 mod_rewrite 的解决方案

使用 mod_rewrite 您可以避免父目录的依赖(硬编码)。

(如果我使用mod_rewrite而不是mod_dir,我将必须RewriteBase以类似的方式根据需要向每个子目录添加。)

你会不是需要RewriteBase在此处添加。事实上,您应该避免RewriteBase在这种情况下添加指令。(不要复制常用的 WordPress 前端控制器模式。)然后使用相对的代换字符串(在RewriteRule指令中)到前端控制器。相对代换字符串与包含文件的目录相关。因此,如果您准备使用 mod_rewrite,.htaccess这当然是一种可以接受的解决方法,可以避免对父目录产生依赖。FallbackResource

而且如果您已经使用 mod_rewrite 进行其他重写,那么使用 mod_rewrite 作为前端控制器模式也可以说是首选解决方案。

mod_rewrite 解决方案与 mod_dir 结合使用DirectoryIndex。对“根”目录本身的请求由 mod_dir 处理,而不是 mod_rewrite。(也就是说,应用程序的“根” - 子目录 - 不一定是 vHost 的“文档根”。)

例如,目录中的所有内容(包括index.php和) :.htaccess/subfolder

# /subfolder/.htaccess

DirectoryIndex index.php

RewriteEngine On

RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]

第一个RewriteRule指令只是一种优化,并非绝对必要,以使它“工作”。此规则避免了在将请求重写为 后进行不必要的文件系统检查index.php。或者,在 Apache 2.4 上,您可以使用 标志END代替L最后一条规则。

在没有指令的情况下RewriteBase,最后一个RewriteRule指令(使用相对的替换字符串)将请求重写为/subfolder/index.php(文件所在的目录.htaccess)。


即使在您确实需要知道父目录的名称的情况下,也可以再次使用 mod_rewrite 来计算。

相关内容