当前位置:  开发笔记 > 编程语言 > 正文

mod_rewrite的隐藏功能

如何解决《mod_rewrite的隐藏功能》经验,为你挑选了5个好方法。

mod_rewrite最近似乎有相当数量的线程浮出水面,对它的某些方面如何工作有点混淆.结果我编写了一些关于常见功能的注释,也许还有一些烦人的细微差别.

您遇到过哪些其他功能/常见问题mod_rewrite



1> Owen..:

在哪里放置mod_rewrite规则

mod_rewrite规则可以放在httpd.conf文件中,也可以放在.htaccess文件中.如果您有权访问httpd.conf,则在此处放置规则将提供性能优势(因为规则处理一次,而不是每次.htaccess调用文件时).

记录mod_rewrite请求

可以从httpd.conf文件中启用日志记录(包括):

# logs can't be enabled from .htaccess
# loglevel > 2 is really spammy!
RewriteLog /path/to/rewrite.log
RewriteLogLevel 2

常见用例

    将所有请求汇集到一个点:

    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 
    

    自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] 
    

    注意:外部重定向是隐含的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]
    

    强制SSL

    RewriteEngine on
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://example.com/$1 [R,L]
    

    常用标志:

    [R][redirect]- 强制重定向(默认为302临时重定向)

    [R=301][redirect=301]- 强制执行301永久重定向

    [L][last]- 停止重写过程(见常见陷阱中的注释)

    [NC][nocase]- 指定匹配应不区分大小写


    使用长形式的标志通常更具可读性,并且可以帮助其他人以后阅读您的代码.

    您可以使用逗号分隔多个标志:

    RewriteRule ^olddir(.*)$ /newdir$1 [L,NC]
    

常见的陷阱

    混合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                 
    

    注意:您可以混合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
    

    [L]不是最后一个!(有时)

    [L]标志停止处理该通过规则集的任何进一步重写规则.但是,如果在该传递中修改了URL并且您在.htaccess上下文或部分中,那么您修改的请求将再次通过URL解析引擎传回.在下一次传球中,这次可能会匹配不同的规则.如果您不理解这一点,通常看起来您的[L]旗帜没有效果.

    # processing does not stop here
    RewriteRule ^dirA$ /dirB [L] 
    # /dirC will be the final result
    RewriteRule ^dirB$ /dirC     
    

    我们的重写日志显示规则运行两次,URL更新两次:

    rewrite 'dirA' -> '/dirB'
    internal redirect with /dirB [INTERNAL REDIRECT]
    rewrite 'dirB' -> '/dirC'
    

    解决这个问题的最好方法是使用[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 ...
    

    或者您必须确保您的RewriteRule位于上下文(即httpd.conf)中,不会导致您的请求被重新解析.


Dude,完全是互联网上最好的文章,现在改写mod.我讨厌那件事.我是一个lighttpd异教徒*因为我多么讨厌mod_rewrite.
这是迄今为止我在mod_rewrite上发现的最有用的指南.刚刚发现RewriteLog有助于修复这么多问题,我花了几天的时间追踪到几分钟.(我的意思是规则是写的,但我无法弄清楚他们为什么不工作)
`[L]`标志表示当前处理中的规则是**最后**,这不会停止重写,因为它们是内部重定向,所以你的`dirB`在下一个htaccess处理中应用于`dirC`.单独`RewriteRule ^(.*)$ index.php?query = $ 1`将是内部重定向的无限循环(实际上它在10次迭代后终止).** - 1**,因为你建议_ [L]不是last_.它不会终止重写过程,但**它是最后的**.
我相信`RewriteCond%{HTTPS} off`是检查HTTPS连接的首选方式(在强制非SSL流量到HTTPS的示例中)

2> 小智..:

如果您需要"阻止"内部重定向/重写发生在.htaccess中,请查看

RewriteCond %{ENV:REDIRECT_STATUS} ^$

条件,如这里所讨论的.



3> Sean McMilla..:

与RewriteBase的交易:

您几乎总是需要设置RewriteBase.如果不这样做,apache会猜测您的base是目录的物理磁盘路径.所以从这开始:

RewriteBase /


有什么方法可以说"RewriteBase.",或者表示它应该保持URL相同的东西,只是改变你指定的内容?
如果在`RewriteRule`指令中使用相对路径替换,则只需要设置`RewriteBase`.最好避免使用相对路径.
我不同意这个答案.在我们的开发团队中,我们完全避免使用"RewriteBase",因为几乎所有开发人员都误解了它的作用.正如@ w3d所说,如果你想保存字符并希望在一个文件中对所有RewriteRules应用相同的基数,你只需要它.如果你避开它,你的代码可能会更清楚.

4> Michael Ekok..:

其他陷阱:

1-有时禁用MultiViews是个好主意

Options -MultiViews

我对所有MultiViews功能都不太熟悉,但我知道它在活动时会弄乱我的mod_rewrite规则,因为它的一个属性是尝试"猜测"它认为我正在寻找的文件的扩展名.

我将解释:假设你的web目录,file1.php和file2.php中有2个php文件,你将这些条件和规则添加到.htaccess:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ file1.php/$1 

您假设所有与文件或目录不匹配的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 

那一个,我真的不知道细节,但我已经看过很多次了,所以就去做吧.



5> DrDol..:

方程可以通过以下示例完成:

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]

动态负载平衡:

如果使用mod_proxy来平衡系统,则可以添加动态范围的工作服务器.

RewriteCond %{HTTP_COOKIE} ^.*stickysession=route\.server([0-9]{1,2}).*$ [NC]
RewriteRule (.*) https://worker%1.internal.com/$1 [P,L]

推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有