Owe*_*wen 119 apache .htaccess mod-rewrite
mod_rewrite
最近似乎有相当数量的线程浮出水面,对它的某些方面如何工作有点混淆.结果我编写了一些关于常见功能的注释,也许还有一些烦人的细微差别.
您遇到过哪些其他功能/常见问题mod_rewrite
?
Owe*_*wen 203
mod_rewrite
规则可以放在httpd.conf
文件中,也可以放在.htaccess
文件中.如果您有权访问httpd.conf
,则在此处放置规则将提供性能优势(因为规则处理一次,而不是每次.htaccess
调用文件时).
可以从httpd.conf
文件中启用日志记录(包括<Virtual Host>
):
# logs can't be enabled from .htaccess
# loglevel > 2 is really spammy!
RewriteLog /path/to/rewrite.log
RewriteLogLevel 2
Run Code Online (Sandbox Code Playgroud)
将所有请求汇集到一个点:
RewriteEngine on
# ignore existing files
RewriteCond %{REQUEST_FILENAME} !-f
# ignore existing directories
RewriteCond %{REQUEST_FILENAME} !-d
# map requests to index.php and append as a query string
RewriteRule ^(.*)$ index.php?query=$1
Run Code Online (Sandbox Code Playgroud)
自Apache 2.2.16起,您也可以使用FallbackResource
.
处理301/302重定向:
RewriteEngine on
# 302 Temporary Redirect (302 is the default, but can be specified for clarity)
RewriteRule ^oldpage\.html$ /newpage.html [R=302]
# 301 Permanent Redirect
RewriteRule ^oldpage2\.html$ /newpage.html [R=301]
Run Code Online (Sandbox Code Playgroud)
注意:外部重定向是隐含的302重定向:
# this rule:
RewriteRule ^somepage\.html$ http://google.com
# is equivalent to:
RewriteRule ^somepage\.html$ http://google.com [R]
# and:
RewriteRule ^somepage\.html$ http://google.com [R=302]
Run Code Online (Sandbox Code Playgroud)强制SSL
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://example.com/$1 [R,L]
Run Code Online (Sandbox Code Playgroud)常用标志:
[R]
或[redirect]
- 强制重定向(默认为302临时重定向)[R=301]
或[redirect=301]
- 强制执行301永久重定向[L]
或[last]
- 停止重写过程(见常见陷阱中的注释)[NC]
或[nocase]
- 指定匹配应不区分大小写
使用长形式的标志通常更具可读性,并且可以帮助其他人以后阅读您的代码.
您可以使用逗号分隔多个标志:
RewriteRule ^olddir(.*)$ /newdir$1 [L,NC]
Run Code Online (Sandbox Code Playgroud)混合mod_alias
风格重定向mod_rewrite
# Bad
Redirect 302 /somepage.html http://example.com/otherpage.html
RewriteEngine on
RewriteRule ^(.*)$ index.php?query=$1
# Good (use mod_rewrite for both)
RewriteEngine on
# 302 redirect and stop processing
RewriteRule ^somepage.html$ /otherpage.html [R=302,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# handle other redirects
RewriteRule ^(.*)$ index.php?query=$1
Run Code Online (Sandbox Code Playgroud)
注意:您可以混合mod_alias
使用mod_rewrite
,但它涉及的工作不仅仅是处理上面的基本重定向.
上下文影响语法
在.htaccess
文件中,RewriteRule模式中不使用前导斜杠:
# given: GET /directory/file.html
# .htaccess
# result: /newdirectory/file.html
RewriteRule ^directory(.*)$ /newdirectory$1
# .htaccess
# result: no match!
RewriteRule ^/directory(.*)$ /newdirectory$1
# httpd.conf
# result: /newdirectory/file.html
RewriteRule ^/directory(.*)$ /newdirectory$1
# Putting a "?" after the slash will allow it to work in both contexts:
RewriteRule ^/?directory(.*)$ /newdirectory$1
Run Code Online (Sandbox Code Playgroud)[L]不是最后一个!(有时)
该[L]
标志停止处理该通过规则集的任何进一步重写规则.但是,如果在该传递中修改了URL并且您在.htaccess
上下文或<Directory>
部分中,那么您修改的请求将再次通过URL解析引擎传回.在下一次传球中,这次可能会匹配不同的规则.如果您不理解这一点,通常看起来您的[L]
旗帜没有效果.
# processing does not stop here
RewriteRule ^dirA$ /dirB [L]
# /dirC will be the final result
RewriteRule ^dirB$ /dirC
Run Code Online (Sandbox Code Playgroud)
我们的重写日志显示规则运行两次,URL更新两次:
rewrite 'dirA' -> '/dirB'
internal redirect with /dirB [INTERNAL REDIRECT]
rewrite 'dirB' -> '/dirC'
Run Code Online (Sandbox Code Playgroud)
解决这个问题的最好方法是使用[END]
标志(请参阅Apache文档)而不是[L]
标志,如果您真的想要停止所有进一步处理规则(以及后续传递).但是,该[END]
标志仅适用于Apache v2.3.9 +,因此如果您使用的是v2.2或更低版本,则只会使用该[L]
标志.
对于早期版本,您必须依赖RewriteCond
语句来防止在URL解析引擎的后续传递中匹配规则.
# Only process the following RewriteRule if on the first pass
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ...
Run Code Online (Sandbox Code Playgroud)
或者您必须确保您的RewriteRule位于上下文(即httpd.conf
)中,不会导致您的请求被重新解析.
小智 21
如果您需要"阻止"内部重定向/重写发生在.htaccess中,请查看
RewriteCond %{ENV:REDIRECT_STATUS} ^$
Run Code Online (Sandbox Code Playgroud)
Sea*_*lan 18
与RewriteBase的交易:
您几乎总是需要设置RewriteBase.如果不这样做,apache会猜测您的base是目录的物理磁盘路径.所以从这开始:
RewriteBase /
Run Code Online (Sandbox Code Playgroud)
Mic*_*oka 13
其他陷阱:
1-有时禁用MultiViews是个好主意
Options -MultiViews
Run Code Online (Sandbox Code Playgroud)
我对所有MultiViews功能都不太熟悉,但我知道它在活动时会弄乱我的mod_rewrite规则,因为它的一个属性是尝试"猜测"它认为我正在寻找的文件的扩展名.
我将解释:假设你的web目录,file1.php和file2.php中有2个php文件,你将这些条件和规则添加到.htaccess:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ file1.php/$1
Run Code Online (Sandbox Code Playgroud)
您假设所有与文件或目录不匹配的URL都将被file1.php抓取.惊喜!对于URL http:// myhost/file2/somepath,此规则不受尊重.相反,你被带到file2.php.
发生了什么事情,MultiViews自动猜到你真正想要的网址是http://myhost/file2.php/somepath,很高兴带你到那儿.
现在,你不知道刚刚发生了什么,你就是在那一点上质疑你认为你对mod_rewrite有所了解的一切.然后,您开始使用规则来尝试理解这种新情况背后的逻辑,但是您测试的越多,它所产生的感觉越少.
好的,简而言之,如果您希望mod_rewrite以接近逻辑的方式工作,关闭MultiViews是朝着正确方向迈出的一步.
2-启用FollowSymlinks
Options +FollowSymLinks
Run Code Online (Sandbox Code Playgroud)
那一个,我真的不知道细节,但我已经看过很多次了,所以就去做吧.
方程可以通过以下示例完成:
RewriteCond %{REQUEST_URI} ^/(server0|server1).*$ [NC]
# %1 is the string that was found above
# %1<>%{HTTP_COOKIE} concatenates first macht with mod_rewrite variable -> "test0<>foo=bar;"
#RewriteCond search for a (.*) in the second part -> \1 is a reference to (.*)
# <> is used as an string separator/indicator, can be replaced by any other character
RewriteCond %1<>%{HTTP_COOKIE} !^(.*)<>.*stickysession=\1.*$ [NC]
RewriteRule ^(.*)$ https://notmatch.domain.com/ [R=301,L]
Run Code Online (Sandbox Code Playgroud)
动态负载平衡:
如果使用mod_proxy来平衡系统,则可以添加动态范围的工作服务器.
RewriteCond %{HTTP_COOKIE} ^.*stickysession=route\.server([0-9]{1,2}).*$ [NC]
RewriteRule (.*) https://worker%1.internal.com/$1 [P,L]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
44139 次 |
最近记录: |