apache的RewriteMap使用心得
在apache的环境下,rewrite还真是生活之友啊,时不时就得用上。前些日子有个需求,要将url重新转一转。
什么情况?
原来的url
http://www.xxx.com/demo/oldpage.php?param1=1¶m2=2
转换后的url
http://www.xxx.com/newpage.php?url=%2Fdemo%2Fmypage.php%3Fparam1%3D1¶m2%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表示使用自定义脚本。现在这个版本总算正常运作了。
作者: Volcano 发表于April 2, 2009 at 9:57 pm
kevin 于 2009-04-07 @ 17:59:42 留言 :
不知采用php脚本的那个方案在高并发下的表现,楼主应测试一下让群众放心那
apache管道记录日志的表现不咋地
Volcano 于 2009-04-07 @ 21:14:33 留言 :
过几天采用php这个方案的版本就要在线上运行了,到时候告诉你答案。另外我测试的时候发现这个脚本跑起来几乎没什么负载,问题不大。
Volcano 于 2009-06-23 @ 23:00:11 留言 :
在实际的高并发环境下运行俩月了,这个方案相当稳定,绝无性能问题。
Sun 于 2009-06-26 @ 14:08:34 留言 :
awesome!