apache的RewriteMap使用心得

在apache的环境下,rewrite还真是生活之友啊,时不时就得用上。前些日子有个需求,要将url重新转一转。

什么情况?

原来的url
http://www.xxx.com/demo/oldpage.php?param1=1&param2=2

转换后的url
http://www.xxx.com/newpage.php?url=%2Fdemo%2Fmypage.php%3Fparam1%3D1&param2%3D2

需要把粗体部分的url进行urlencode,能看出上面的字符”?&=”都分别转义过,作为参数发给另外一个url。那么这时候请出rewrite还真是最合适不过了。

坎坷的Rewrite经历

查查rewrite手册,俺这才知道,转义这活,非得派出RewriteMap的map function才能做的比较漂亮。现在只有四个内部map function可供差遣:

  • toupper: Converts the key to all upper case.
  • tolower: Converts the key to all lower case.
  • escape: Translates special characters in the key to hex-encodings.
  • unescape: Translates hex-encodings in the key back to special characters.

那么很快就有了第一个rewrite出现:


RewriteMap escape int:escape
RewriteRule ^/([^/]*)$ /newpage.php?mi_url_suffix=${escape:$1?%{QUERY_STRING}} [L,PT]

注:这里的int不是intger的意思,它是internal的缩写,表示调用内部函数。

看上去非常简单,跑起来貌似也正….常?且慢,俺打开RewriteLog一瞅,形式不容乐观啊,”&”字符通通没有转义。看来是失败了,爬到狗狗上翻了一下,貌似escape对”?=”之类的特殊字符是不做转义的,晕。

RewriteMap到底

接着细看apache的rewrite手册,发现RewriteMap还支持自定义脚本,那么还得使出俺的看家绝技——php了。首先弄一个能转义的php,必须非常简单,复杂了apache容易挂掉,写出来发现想复杂都挺难啊:

/usr/local/bin/escape.php

#!/usr/bin/php -f
<?php
while($in = trim(fgets(STDIN)))
        fputs(STDOUT, urlencode($in) . "\r\n");
?>

在这个脚本里可别使用php:://stdin之类的,具体原因查php手册。相应的,rewrite规则如下:


RewriteMap escape prg:/usr/local/bin/escape.php
RewriteRule ^/([^/]*)$ /newpage.php?mi_url_suffix=${escape:$1?%{QUERY_STRING}} [L,PT]

rewrite规则没有太大的改变,prg表示使用自定义脚本。现在这个版本总算正常运作了。

8 Replies to “apache的RewriteMap使用心得”

  1. 不知采用php脚本的那个方案在高并发下的表现,楼主应测试一下让群众放心那

    apache管道记录日志的表现不咋地

  2. 过几天采用php这个方案的版本就要在线上运行了,到时候告诉你答案。另外我测试的时候发现这个脚本跑起来几乎没什么负载,问题不大。

  3. 不知道用RewriteMap能不能做到,像我下面这样的要求:
    我想将一个URL串中的小括号及|都换成下划线,不知道像我下面这样写的代码为什么不行:
    楼主能不能相告,

    比如我想将一个URL地址为:“mp3-players/Mp3(grand|purple|varsity|maize)white.html”替换为“mp3-players/Mp3_grand_purple_varsity_maize_white.html”不晓得像我下面这样写的代码行不行:
    下面这两行代码是我写在“.htaccess”里面的
    RewriteMap tryme prg:/cgi-bin/andy.php
    RewriteRule ^(.+\/.+\.html)$ http://www.myweb.com/${tryme:$1|0} [L,R=301]

    下面是我存在网站根目录下的cgi-bin目录里面的“andy.php”脚本文件

    #!C:/wamp/bin/php/php5.2.6/php.exe -f

    我一直在试,不知道为什么上面这样类似的脚本总是不行,因为我的一个网站挂在一个linux上面,而GOOGLE不认多次的301重定向,所以我就想结合使用RewriteMap直接一次给它定向过去

  4. 我对RewriteMap中有几个地方不知道,
    第一、写在.htaccess里的规则中的RewriteMap 后面跟的串里的地址,是应该用那个脚本文件的绝对路径,还是用相对于该.htaccess位置的相对路径。
    第二、写在脚本文件里的文字中的第一行“#!C:/wamp/bin/php/php5.2.6/php.exe -f”是代表什么意思,我在google上搜索,好像别人的都不带那个-f选项,为什么你的规则里面要带这个选项,还里这边的路径是不是代表php安装包的相对路径。

Leave a Reply

Your email address will not be published.