mod_rewrite 的隐藏功能 [英] Hidden features of mod_rewrite

查看:24
本文介绍了mod_rewrite 的隐藏功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近似乎有相当多的 mod_rewrite 线程在四处流动,但对其某些方面的工作方式有些困惑.因此,我整理了一些关于常见功能的笔记,也许还有一些烦人的细微差别.

There seem to be a decent number of mod_rewrite threads floating around lately with a bit of confusion over how certain aspects of it work. As a result I've compiled a few notes on common functionality, and perhaps a few annoying nuances.

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

What other features / common issues have you run across using mod_rewrite?

推荐答案

在哪里放置 mod_rewrite 规则

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

Where to place mod_rewrite rules

mod_rewrite rules may be placed within the httpd.conf file, or within the .htaccess file. if you have access to httpd.conf, placing rules here will offer a performance benefit (as the rules are processed once, as opposed to each time the .htaccess file is called).

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

Logging may be enabled from within the httpd.conf file (including <Virtual Host>):

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

常见用例

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

  1. To funnel all requests to a single point:

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.

Since Apache 2.2.16 you can also use FallbackResource.

处理 301/302 重定向:

Handling 301/302 redirects:

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 重定向:

Note: external redirects are implicitly 302 redirects:

# 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

  • Forcing SSL

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

  • 常见标志:

  • Common flags:

    • [R][redirect] - 强制重定向(默认为 302 临时重定向)
    • [R=301][redirect=301] - 强制 301 永久重定向
    • [L][last] - 停止重写过程(见下面常见陷阱的注释)
    • [NC][nocase] - 指定匹配不区分大小写
    • [R] or [redirect] - force a redirect (defaults to a 302 temporary redirect)
    • [R=301] or [redirect=301] - force a 301 permanent redirect
    • [L] or [last] - stop rewriting process (see note below in common pitfalls)
    • [NC] or [nocase] - specify that matching should be case insensitive


    使用长格式的标志通常更具可读性,有助于其他人稍后阅读您的代码.


    Using the long-form of flags is often more readable and will help others who come to read your code later.

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

    You can separate multiple flags with a comma:

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

    Note: you can mix mod_alias with mod_rewrite, but it involves more work than just handling basic redirects as above.

    上下文影响语法

    .htaccess 文件中,RewriteRule 模式中不使用前导斜杠:

    Within .htaccess files, a leading slash is not used in the RewriteRule pattern:

    # 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] is not last! (sometimes)

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

    The [L] flag stops processing any further rewrite rules for that pass through the rule set. However, if the URL was modified in that pass and you're in the .htaccess context or the <Directory> section, then your modified request is going to be passed back through the URL parsing engine again. And on the next pass, it may match a different rule this time. If you don't understand this, it often looks like your [L] flag had no effect.

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

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

    Our rewrite log shows that the rules are run twice and the URL is updated twice:

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

    解决此问题的最佳方法是使用 [END] 标志 (查看 Apache 文档) 而不是 [L] 标志,如果你真的想停止所有进一步的规则处理(和后续的传递).但是,[END] 标志仅适用于 Apache v2.3.9+,因此如果您使用的是 v2.2 或更低版本,则只能使用 [L] 标志.

    The best way around this is to use the [END] flag (see Apache docs) instead of the [L] flag, if you truly want to stop all further processing of rules (and subsequent passes). However, the [END] flag is only available for Apache v2.3.9+, so if you have v2.2 or lower, you're stuck with just the [L] flag.

    对于早期版本,您必须依靠 RewriteCond 语句来防止 URL 解析引擎后续传递的规则匹配.

    For earlier versions, you must rely on RewriteCond statements to prevent matching of rules on subsequent passes of the URL parsing engine.

    # Only process the following RewriteRule if on the first pass
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule ...
    

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

    Or you must ensure that your RewriteRule's are in a context (i.e. httpd.conf) that will not cause your request to be re-parsed.

    这篇关于mod_rewrite 的隐藏功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆