背景
我正在构建一个使用MVC原则的PHP
应用程序。我并不是很擅长编写.htaccess
文件,但是我有一个非常适合我的应用程序的解决方案。为了安全起见,所有的请求都被路由到public/
目录,并且只有这个目录中的绝对资源可以访问,例如:http://localhost/public/css/main.css
.
我的问题是正确处理实际上不存在的资源文件(js
、css
或图像)。
问题与疑问
当资源文件(js
、css
或图像)不存在时,我当前的.htaccess
规则会导致无限循环并返回http 500
状态。
我知道我需要捕获这个file does not exists
问题并返回一个http 404
状态,但是我如何在不跳过我的规则的最后4行的情况下做到这一点呢?我指的是最后3个重写条件和1个重写规则。这些对我的应用程序至关重要。
htaccess代码
# Disable index view.
Options -Indexes
# Hide sensitive files.
<Files ~ "\.(env|json|config|md|gitignore|gitattributes|lock|yml|xml)$">
Order allow,deny
Deny from all
</Files>
# Redirect all requests to the public directory.
<IfModule mod_rewrite.c>
RewriteEngine On
# Rewrite base if site is not at the servers root.
RewriteBase /sub/directory/
# If nothing or an index page is requested go to `public/index.php` and stop processing.
RewriteRule ^(\/||.*index\..*)$ public/index.php [L,QSA]
# If the URL already contains the `public/` directory go to URL and stop processing.
RewriteRule ^(.*public\/.*)$ $1 [L,QSA]
# Does it appear that this URL is for a resource (JS, CSS, etc.)?
# ▼ ▼ ▼ ISSUE STARTS HERE ▼ ▼ ▼
RewriteCond %{REQUEST_URI} ^([\w\d\s\-\_\/\%]*)\.(?!php|phtml|htm|html).*$
# Yes, prefix with `public/` and go to the modified URL.
RewriteRule ^(.*)$ public/$1 [L,QSA]
# Rewrite all remaining URLs to our apps MVC structure.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^([\w\d\s\-\_\/\%]*)$ public/index.php?p=$1 [L,QSA]
</IfModule>
2条答案
按热度按时间yks3o0rb1#
你的问题方法不对。你 * 假设 * 你必须“捕捉”文件未找到的情况并返回404。但事实并非如此。实际上这是apache http服务器的默认行为,所以你不必为此做任何事情。你的问题是你为这些请求实现了一个重写循环。这就是你需要打破的。然后一个404将作为标准响应返回。
实际的问题是一个经典的问题:您的上一个重写规则重写为
public/index.php
。但是,该目标 * 再次 * 与同一重写规则的模式匹配。因此,您的下一个重写目标看起来像public/index.php?p=public/index.php&p=some-page
。每次规则重写时,重写都会重新开始,因为目标已被更改。该行为已记录在案。您有两个选项:
您需要在该规则中使用
END
标志而不是L
标志(以 * 最终 * 终止该请求的重写过程:或者,您需要添加一个附加条件来中断该循环:
我肯定会重新评论第一种方法,假设这里没有进一步的重写步骤干扰。
svdrlsy42#
arkascha's answer帮助我指明了正确的方向;在正确的位置使用
END
而不是L
。对于那些希望创建类似的以安全为中心的MVC结构的人,我的工作文件.htacces
如下。它提供了以下好处:index
页面的尝试都将被重定向到public
目录。[B]public
目录的重写循环。[C]public
目录中的资源文件(JS、CSS等)。[D]404
而不是500
。再次感谢@arkascha指出L
和END
在htacces
文件中的区别。[E]