特定文件的mod_rewrite异常

时间:2012-10-12 19:26:14

标签: php .htaccess apache

我的页面没有重定向,因为我的.htaccess文件被设置为:

RewriteEngine on  
RewriteCond $1 !^(index\.php|resources|robots\.txt)  
RewriteCond %{REQUEST_FILENAME} !-f  
RewriteCond %{REQUEST_FILENAME} !-d  
RewriteRule ^(.*)$ index.php/$1 [L,QSA]   

我将此设置用于我的MVC框架,所以我得到像/controller/method/argument这样的网址,但是当我重定向到/forum/login.php时,它会切换到/ forum /.

如何将此作为例外添加,以便我能够重定向到/forum/login.php

我在/ forum /目录中发现另一个.htaccess也可能导致问题?

# BEGIN PunBB

<IfModule mod_rewrite.c>
    # MultiViews interfers with proper rewriting
    Options -MultiViews

    RewriteEngine On

    # Uncomment and properly set the RewriteBase if the rewrite rules are not working properly
    #RewriteBase /

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . rewrite.php [L]
</IfModule>

2 个答案:

答案 0 :(得分:22)

首先我会告诉你如何阅读你的RewriteRule:

您从第一个(或下一个)RewriteRule条目开始:

RewriteRule ^(.*)$ index.php/$1 [L,QSA]

第一个参数是一个可以匹配您请求的URL的正则表达式。 ^(.*)$匹配所有内容,并将此“所有内容”存储在一个可以在以后使用的变量中。

仅当前面有RewriteCond条目时,才会对它们进行评估:

RewriteCond $1 !^(index\.php|resources|robots\.txt)

$1是对RewriteRule的第一个括号内匹配的内容的引用。这与第二个参数进行比较,第二个参数是表示几个显式名称的正则表达式,!否定表达式,例如只有当正则表达式不匹配时,此规则才允许执行RewriteRule。如果此条件返回true,则将查看下一个条件。

RewriteCond %{REQUEST_FILENAME} !-f

如果请求的文件名不是硬盘上的真实文件,则此条件为真。

RewriteCond %{REQUEST_FILENAME} !-d

如果请求的文件名不是真实目录,则此条件为真。

只有当所有这些条件都成立时(它们与AND链接在一起),我们才会回到重写规则:

RewriteRule ^(.*)$ index.php/$1 [L,QSA]

此重写步骤的结果定义为第二个和第三个参数。再次使用$1作为匹配的内容,并且参数定义此规则(如果最初匹配)将是最后一个规则(L),并且将重写在重写目标中定义的任何查询字符串到原始URL(QSA)中的任何查询字符串。

批判:

MVC框架的通常重写尝试尽可能高效。您的重写条件都必须进行评估才能成功重写。只有当任何RewriteCond返回false时,才会停止。每个被重写的请求都需要进行大量的cpu密集测试。首先是RewriteRule正则表达式,然后是第一个RewriteCond中的正则表达式,然后对文件系统进行两次硬盘测试,以便存在文件。

另一方面,第一个RewriteCond似乎是不必要的。它测试某些名称,如果找到,则中止重写。 “index.php”应该被第二个RewriteCond检测到,因为它是一个现有文件(如果不是,那么重写将如何工作)。任何以“资源”开头的东西也会匹配,但可能不应该出于同样的原因:第二个RewriteCond会找到现有资源。最后是“robots.txt”文件。如果您想在机器人获取您的网站时避免使用404,那么最好有一个,可能是emtpy。

由于您没有更改查询字符串中的任何内容,因此不需要[QSA]指令。

改进:

RewriteEngine on  
RewriteCond %{REQUEST_FILENAME} -f [OR] 
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [L]  
RewriteRule ^.*$ index.php [L]

第一个RewriteRule将匹配整个请求的路径。两个RewriteCond与[OR]连接,因此返回true的第一个RewriteCond将取消进一步的评估。第一个RewriteCond测试所请求的文件是否存在。如果存在,则返回true,处理返回到第一个RewriteRule。目标表达式为“ - ”,表示“不重写”。 [L]停止进一步处理重写规则。所以最后,对于现有文件,我们只有一个正则表达式和一个文件系统测试,之后,这个现有文件将被发送到浏览器。

如果没有找到文件,第一个RewriteRule和RewriteCond将不会触发,因此[L]不会停止该过程。所以第二个RewriteRule被执行了。这个是无条件的,正则表达式与之前相同,匹配所有内容,并将其重写为“index.php”。

如果存在任何文件,则此重写不会调用index.php,包括/forum/login.php。

如果您希望继续解析RewriteRule ^.*$ index.php/$0 [L]而不是$_SERVER['PATH_INFO'],则可以将第二个更改为$_SERVER['REQUEST_URI']

答案 1 :(得分:2)

试试这个:

RewriteEngine on  
RewriteCond $1 !^(index\.php|forum|resources|robots\.txt)  
RewriteCond %{REQUEST_FILENAME} !-f  
RewriteCond %{REQUEST_FILENAME} !-d  
RewriteRule ^(.*)$ index.php/$1 [L,QSA]   

而且:

# BEGIN PunBB

# ----------------------------------------------------------------------
# Start rewrite engine
# ----------------------------------------------------------------------

<IfModule mod_rewrite.c>
    # MultiViews interfers with proper rewriting
    Options -MultiViews

    RewriteEngine On

    # Uncomment and properly set the RewriteBase if the rewrite rules are not working properly
    RewriteBase /forum/

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . rewrite.php [L]
</IfModule>


# ----------------------------------------------------------------------
# Better website experience for IE users
# ----------------------------------------------------------------------

# Force the latest IE version, in various cases when it may fall back to IE7 mode
# github.com/rails/rails/commit/123eb25#commitcomment-118920
# Use ChromeFrame if it's installed for a better experience for the poor IE folk

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        BrowserMatch MSIE ie
        Header set X-UA-Compatible "IE=Edge,chrome=1" env=ie
    </IfModule>
</IfModule>

<IfModule mod_headers.c>
    # Because X-UA-Compatible isn't sent to non-IE (to save header bytes),
    # We need to inform proxies that content changes based on UA
    Header append Vary User-Agent
    # Cache control is set only if mod_headers is enabled, so that's unncessary to declare
</IfModule>


# ----------------------------------------------------------------------
# UTF-8 encoding
# ----------------------------------------------------------------------

# Use UTF-8 encoding for anything served text/plain or text/html
AddDefaultCharset utf-8

# Force UTF-8 for a number of file formats
AddCharset utf-8 .html .css .js .xml .json .rss


# ----------------------------------------------------------------------
# A little more security
# ----------------------------------------------------------------------

# Do we want to advertise the exact version number of Apache we're running?
# Probably not.
## This can only be enabled if used in httpd.conf - It will not work in .htaccess
# ServerTokens Prod


# "-Indexes" will have Apache block users from browsing folders without a default document
# Usually you should leave this activated, because you shouldn't allow everybody to surf through
# every folder on your server (which includes rather private places like CMS system folders).
<IfModule mod_autoindex.c>
    Options -Indexes
</IfModule>

# END PunBB