apache - mod_rewrite 的隐藏功能

标签 apache .htaccess mod-rewrite

最近似乎有相当数量的 mod_rewrite 线程在流动,但对其某些方面的工作原理有些困惑。因此,我编写了一些关于常见功能的注释,也许还有一些令人讨厌的细微差别。

您在使用 mod_rewrite 时还遇到过哪些其他功能/常见问题?

最佳答案

在哪里放置 mod_rewrite 规则

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

记录 mod_rewrite 请求

可以从 httpd.conf 内启用日志记录文件(包括 <Virtual Host> ):

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

常见用例

  1. 将所有请求集中到一个点:

    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 .

  2. 处理 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]
    
  3. 强制使用 SSL

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

    • [R][redirect] - 强制重定向(默认为 302 临时重定向)
    • [R=301][redirect=301] - 强制 301 永久重定向
    • [L][last] - 停止重写过程(请参阅下面常见陷阱的注释)
    • [NC][nocase] - 指定匹配不区分大小写


    使用长格式的标志通常更具可读性,并且会帮助其他人稍后阅读您的代码。

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

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

常见陷阱

  1. 混合 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_aliasmod_rewrite ,但它涉及的工作不仅仅是处理上面的基本重定向。

  2. 上下文影响语法

    .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
    
  3. [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     
    

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

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

    解决这个问题的最佳方法是使用 [END]标志( see Apache docs )而不是 [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 )不会导致您的请求被重新解析。

关于apache - mod_rewrite 的隐藏功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/286004/

相关文章:

javascript - 5 秒后重定向,但只允许引用者访问该页面

apache - Laravel SSL .htaccess 重定向到 index.php

php - .htaccess URL 重写失败 - 在此服务器上找不到请求的 URL

php - 将动态 url 重定向到 htaccess 中的另一个动态 url

.htaccess - 隐藏子域的子文件夹

.htaccess - 将旧网站重定向到主域,但也将一些内容重定向到主域的子域

php - htaccess 最佳实践

php - Apache htaccess mod 在 PHP 索引页中使用 Controller GET 变量重写重定向

php - 在 Apache 服务器上的 .PHP 文件中存储敏感信息有多安全?

java - 使用jsp保持用户登录