zoukankan      html  css  js  c++  java
  • Apache rewrite配置注意事项

    mod_rewrite的坑太多。

    1、无法取得$_SERVER[‘SCRIPT_NAME’]

    当添加rewrite后,写下如此的规则

    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
    RewriteRule ^(.*)$ /index.php/$1 [QSA,L]

    打开phpinfo,发现$_SERVER[‘SCRIPT_NAME’]为”no value”,这在需要判断script_name的单入口mvc中可能是致命的,因为它可能需要用来取得rewrite过的路径。解决方法是在RewriteRule规则修饰添加PT标记。

    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
    RewriteRule ^(.*)$ /index.php/$1 [QSA,PT,L]

    根据rewrite手册的描述,passthrough|PT标记为:

    Forces the resulting URI to be passed back to the URL mapping engine for processing of other URI-to-filename translators, such as Alias or Redirect.

    强制rewrite的URI结果传递给映射引擎(mapping engine)处理其它URI与filename的解析,比如别名Alias或转向Redirect。

    那么passthroungh到底是如何工作的呢?

    The target (or substitution string) in a RewriteRule is assumed to be a file path, by default. The use of the [PT] flag causes it to be treated as a URI instead. That is to say, the use of the [PT] flag causes the result of the RewriteRule to be passed back through URL mapping, so that location-based mappings, such as Alias, Redirect, or ScriptAlias, for example, might have a chance to take effect.

    rewrite后的结果默认会被假定为一个文件路径,而[PT]标记的使用则使字串被当作一个URI(url资源)来对待,也就是说,[PT]标记的使用导致RewriteRule处理的结果又被传回到了URL mapping,这样方便基于文件路径的映射计算。举例:

    Alias "/icons" "/usr/local/apache/icons"
    RewriteRule "/pics/(.+).jpg$" "/icons/$1.gif" [PT]

    此例中,省略[PT]标记的结果就是上面的Alias(别名)替换规则被忽略,造成返回“File not found”。因为在路径/icons中无法找到*.gif,它实际指向了/user/local/apache/icons/*.gif。

    实际,RewriteRull加[PT]标记的流程就是:

    uri –> filepath –> [pt] –>uri(replace)->filepath

    本来我们将用户请求的uri地址映射到服务器系统中实际的文件路径,找到脚本来处理,但因为pt标记,它还需要将rewrite的结果再转回一串uri资源,查找替换回真正的路径地址。

    实际最后返回的还是一个路径,只不过多了一层映射关系。

    PT 标记隐含带有 L 标记的作用: 将停止rewrite,以便传递到下一阶段的处理请求。

    值得一提的是PT在每个目录环境是暗中发挥作用的,例如 <Directory> 块中或 .htaccess 文件中。避免这一作用的唯一办法就是将匹配rewrite为  -。因此,在.htaccess中的RewriteRule的修饰,在有PT的情况下,不必再加L标记。

    说了这么多,还没有交待PT标记与SCRIPT_NAME的关系。实际上这里也没交待,唯一能猜测的就是,SCRIPT_NAME值就是在这里被加上去的。

    2、RewriteCond在conf与.htaccess中的不同。

    具体的错误参考这篇博客

    在httpd.conf中,如果RewriteConf不添加%{DOCUMENT_ROOT}的地址,input出现的将是相对地址"/a./b"映射后的rewrite,将是'/a/b' -> 'index.php/a/b'。

    [rid#9e8030/initial] (4) RewriteCond: input='/a/b' pattern='!-s' => matched

    加上后才会出现绝对地址:

    RewriteCond: input='D:/Tomcat/webapps/ROOT/a/b' pattern='!-s' => not-matched

    这是因为在文件系统(.htaccess)中,默认就是:

    <IfModule rewrite_module>
        RewriteBase /
    </IfModule>

    因此, .htaccess中的rewrite是相对于.htaceess所在路径的。而在conf中是不能使用RewriteBase标记当前根目录的。

    所以,在conf中的rewrite的正确写法应该是:

    RewriteCond  %{DOCUMENT_ROOT}%{REQUEST_FILENAME}   !-s
    RewriteRule  ^/(.*)$  /index.php/$1   [QAS,L]

    注意,index.php前面需要加前导/,代表的是DOCUEMENT_ROOT目录下的index.php文件,不加会丢失DOCUMENT_ROOT(在.htaccess不必)。

    3、.htaccess的配置事项

    1)、重写规则的说明。

    RewriteRule指令是真正重写的工作区间。此指令可以多次使用,每条指令定义一个单一的重写规则。其中定义这些规则的顺序非常重要 — — 这是将在运行时应用的顺序。

    Pattern 是 perl 兼容的正则表达式。第一次运用rewrite规则,它对照 (已解码%) 请求的URL-path,或在per-directory (见下文),URL 路径相对于当前目录环境 。随后的模式对照上次匹配重写规则的输出。

    2)、如何匹配

    在VirtualHost(虚拟主机)方面,Pattern,将是匹配 完主机名和端口剩下的URL部份,在查询字符串(query string)之前匹配 (例如"/ app1/index.html")。
    在Directory和 htaccess 环境,在删除能够引导服务器至当前的RewriteRule的前缀后,Pattern将优先匹配为filesystem路径 (例如"app1/index.html"或"index.html"根据指令在哪里定义) 。
    如果你想匹配的机名、 端口或查询字符串,分别 使用%{HTTP_HOST},{SERVER_PORT} %或 %{QUERY_STRING} 等RewriteCond。

    3、目录中的重写

    可以一些额外的工作在.htaccess 文件中和 <Directory>块中使用rewrite引擎。
    在这样的环境中使用rewrite引擎,您需要设置"RewriteEngine On",而且必须启用"Options FollowSymLinks"。如果管理员在用户目录中禁用了FollowSymLinks,则不能使用rewrite引擎。这是出于安全的需要。

    当在 .htaccess文件使用rewrite引擎时,单目录前缀(对于指定的目录都是相同的)会被RewriteRul匹配模式自动移除,并且会被规则集自动地替换为相对的前缀(不能为前导斜线/或通道名protocal name,例如http://开头)。有关相对替换前缀的详细介绍参见RewriteBase指令。

    如果需要在单目录中(.htaccess)匹配完整的URL路径,请在RewriteCond使用%{REQUEST_URI}变量。

    移除的前缀通常以斜杠/结尾,意为匹配结果将永远不会出现前导斜线/开头,因此,^/的 Pattern(匹配模式)将不会找到匹配。(注:通常在.htaccess中的匹配路径为^(.*)$)。举例,

    如果请求url为http://www.xxx.com/a/b/c,那么,在a目录下建立的.htaccess,匹配得到的uri资源对应的将是:

    b/c

    而非

    /b/c

    在RewriteDebug中看到的替换结果将是:

    rewrite 'b/c' -> 'index.php/b/c'

    虽然重写规则语法规则允许使用在<Location> and <Files>块(包括相应的正则表达式),但这是不必要,也是永远不支持的做法,这样产生的一个可能性就是会破坏上下文已经建立的其它重写规则。

    4、一点不解

    在我的Apache/2.2.25 (Win32) mod_fcgid/2.3.6版本中,.htaccess的设置没问题

    AcceptPathInfo On

    <IfModule rewrite_module>
        RewriteEngine On
        RewriteBase /
        Options FollowSymlinks ExecCGI -Indexes

        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L,NS]
    </IfModule>

    但始终不能rewrite成功,相同的配置下Apache/2.2.29 fpm-cig却可以。是不是因为VirtualHost的缘故?!

    最后只能通过?号参数的形式简接rewrite:

    <IfModule rewrite_module>
        RewriteEngine On
        RewriteBase /
        Options FollowSymlinks ExecCGI -Indexes

        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L,NS]
    </IfModule>

  • 相关阅读:
    16、cgminer学习之:popen函数和system函数详解(执行系统命令)
    16、cgminer学习之:pthread_mutex_init和pthread_cond_init
    15、python学习手册之:元组、文件及其他
    15、python学习手册之:列表和字典
    Chorme浏览器中使用flash debug版本
    Best Practices
    Titled-Contributing to Tiled
    Titled
    VS2010配合SVN搭建使用
    Google code问题记录
  • 原文地址:https://www.cnblogs.com/sumsung753/p/4672289.html
Copyright © 2011-2022 走看看