理解mod_rewrite和正则表达式

时间:2014-02-16 23:08:47

标签: regex apache .htaccess mod-rewrite

我真的很难用正则表达式和mod_rewrite,我想更好地理解。我有一些重写脚本以及我“思考”正在发表的评论。如果我准确描述了正在发生的事情,请告诉我。谢谢

# don't do the following if Apache isn't configured with mod_rewrite
<IfModule mod_rewrite.c>

# self explanatory
RewriteEngine on

# Reference everything from Apache root (i.e. /var/www/html)
RewriteBase /

# Create a condition if statement and execute the following rules until the next condition is reached.
# This one checks if the request is a valid directory, a valid file, or a valid symbolic link
# The % symbol has something to do with backreference of the matched string in the condition.
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l

# Don't do anything (how?), and the [L] means to not match this condition anymore
RewriteRule ^ - [L]

# ^ and $ are the start and end of the patern.
# ([^/]+) takes all characters up to the first /,
# and then adds one more character because the + which is the /,
# and stores it as $1.
# It will only be matched, however, if a / follows plus 0 or 1 character due to the ?.
# Then redirect by adding ?p=$1 where $1 is the stored variable described above.
# The L flag means don't try to do it again, and QSA somehow adds the previous URL to it.
RewriteRule ^([^/]+)/?$ ?p=$1 [L,QSA]

# close if statement
</IfModule>

1 个答案:

答案 0 :(得分:1)

重写条件影响紧随其后的规则,这意味着这里有3个条件:

RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l

仅适用于紧随其后的规则:

RewriteRule ^ - [L]

并且它不会应用于底部的规则。条件本质上意味着:任何现有的文件,目录或符号链接。 %不是后引用,它表示重写变量,在%{REQUEST_FILENAME}的情况下,它是由URL文件映射处理器映射到的文件名。例如,如果网址为http://example.com/some/path/and/file.php,则%{REQUEST_FILENAME}类似于/var/www/localhost/htdocs/some/path/and/file.php,假设您的文档根目录为/var/www/localhost/htdocs/

在:

RewriteRule ^ - [L]

规则匹配所有内容(^匹配字符串的开头,这实际上意味着所有内容)而-意味着,不要更改URI,只需传递它。 [L]标志停止重写。这很重要的原因是重写引擎将无限期地循环所有规则(或者直到达到内部递归限制)或者直到URI停止更改。这会完全停止重写,因为输入URI未更改。

模式:

^([^/]+)/?$ 

表示:任何非/的内容,最后都有可选的/?表示前一个字符是可选的。因此,path/file.php之类的请求将无法匹配,因为它中间有一个/。但是path/会匹配。 path部分使用( )字符进行分组,并使用$进行反向引用。结果将是:

/?p=path

QSA标志附加任何现有的查询字符串,因此请求如下:

/path-name/?foo=bar

被重写为:

/?p=path-name&foo=bar

如果没有QSA,则&foo=bar将不在那里。