apache RewriteMap MapSource自定义规则使用手记

10.1期间,一位朋友问我一个apache的 Rewrite规则中一个高级语法RewriteMap的用法问题。其想要实现的是这个功能,有个多用户的blog,用户访问的时候,是用三级域名访问的。比如http://cfc4n1.blog.cnxct.com,http://cfc4n2.blog.cnxct.com这种三级域名。在服务器上,是对三级域名做泛解析。每个三级域名都生成了一个静态的html主页文件。由于用户数量较多,linux ext硬盘格式上同一目录文件太多,检索文件的速度会有折扣,遂将文件打散到不同的目录下。打散方式是以用户名【三级域名中的cfc4n1,cfc4n2等】的MD5值的每隔两位作为一个目录。MD5的默认长度是32位,每隔两位分一次目录的话,那就有16级目录。每级目录的目录名是2个字符,每个字符的有16种可能【0-9a-f】,那么每级目录的目录数为256个目录,16级的话就有4096个目录。每个目录存1000个文件的话,可以存放4096000个文件,这样做,即可以把文件均匀打散到各个小目录中,同时,每个目录下的文件数又不是很多。当用户访问的时候,取目录里的用户名,计算MD5hash,做字符分割,重写到对应的目录下的文件中,如果文件不存在,则重写到生成这个文件的动态页面中。

到apache手册里找了下RewriteMap的用法

RewriteMap MapName MapType:MapSource

遂顺手在.htaccess里这么写了

RewriteMap cfc prg:/var/www/1.php
RewriteRule ^([a-f0-9-]+)\.blog\.cnxct\.com ${cfc:$1} [L,PT]

然后访问一个三级域名试试。结果提示500 http 错误。到apache日志里看到如下

/var/www/.htaccess: RewriteMap not allowed here

搜了半天,不知道是什么错误,只好再次看手册,这时候,才发现rewritemap的作用域却是server config, virtual host,真汗了一下。自己没认真看手册。
改到virtual host里之后,重启apache,结果,还是http 500。再到错误日志里查个究竟。里面记录的确实(13)Permission denied: mod_rewrite: could not start RewriteMap program /var/www/1.php。呃,权限,权限。。赶紧chmod了一下。再次启动,却提示404。。。 /0a/c1/…./…html那种MD5字符串切割之后的文件找不到。但目录里确实是存在的啊。又到日志里查看,原来却是/0a/c1/…../…html\r 文件无法找到了。为什么地址后面多个\r呢?打开MapSource的脚本文件,才看到里面PHP操作流的结束字符里是“\r\n”了,去掉\r 才可以。

总结一下使用APACHE URL REwrite的RewriteMap方法要注意以下几点:

  • 作用域-server config, virtual host,其他配置里无效。
  • 自定义规则MapSource中流的结束符要跟操作系统符合,linux的要用“\n”,同时,切记在win平台编辑脚本传到linux上的时候,文件换行符要用linux格式的,不然,同样会出现问题。
  • 要给apache赋予对脚本的读权限。
  • apache会在启动的时候,将自定义规则的脚本读取到内存中,之后,再次修改脚本时,不会立刻生效,需要重启 apache
  • apache 的error.log中会记录[warn] mod_rewrite: Running external rewrite maps without defining a RewriteLock is DANGEROUS!这样的错误日志,在apache2.conf【我的系统是ubuntu,其他linux在httpd.conf中】中添加RewriteLock /etc/apache2/script/cfc.lock来指定RewriteLock的文件位置。记得给apache对script目录下有读写权限。

自定义脚本的代码格式如下:

<?php
while($in = trim(fgets(STDIN)))
        fputs(STDOUT, getfile($in)."\n");
function getfile($str)
{
//函数判断文件是否存在等逻辑
}

URL REwrite fox xoops

只写了news,tag,newbb,profile,extgallery这几个模块!
需要apache 的 Rewrite module 的支持!

1,将.htaccess,rewrite_url.php 两个文件复制到xoops主目录下.
2,如果你的xoops不是您网站的根目录,请按照一下操作,否则,请跳过此条,直接进行第3条!
如果您的网站类似这个url http://www.xxx.com/xoops 的话,请打开.htaccess ,找到
#RewriteBase ,去掉前面的# ,后面加上 /xoops, 使之成为RewriteBase /xoops ,保存
3,打开mainfile.php,找到
define(“XOOPS_CHECK_PATH”, 0);
在其下面添加 include “rewrite_url.php”;
4,清除缓存,刷新即可!

附帖子地址:http://xoops.org.cn/modules/newbb/viewtopic.php?topic_id=20353

.htaccess

RewriteEngine On

#如果你的xoops不是在网站根目录,请填写目录名,比如:
#http://xx.com/xoops ,那么请将#RewriteBase前的#去掉,并且,改为 RewriteBase /xoops ,如果是根目录,请保持不变

#RewriteBase 

#RewriteCond %{REQUEST_FILENAME}   !-f

#all
RewriteRule ^(profile|pm|news|gamaps|extgallery|contact)/index.html$ modules/$1/index.php

#profile
RewriteRule ^profile/([a-zA-Z_-]+).html$ modules/profile/$1.php
RewriteRule ^profile/userinfo.php.*$ modules/profile/userinfo.php$1
RewriteRule ^profile/([0-9]+).html$ modules/profile/userinfo.php?uid=$1
RewriteRule ^profile/edit-([0-9]+).html$ modules/profile/edituser.php?uid=$1

# newbb
RewriteRule ^newbb/forum-(d+).html$ modules/newbb/viewforum.php?forum=$1
RewriteRule ^newbb/rss-(d+).html$ modules/newbb/rss.php?f=$1
RewriteRule ^newbb/thread-(d+)-(d+).html$ modules/newbb/viewtopic.php?topic_id=$1&forum=$2
RewriteRule ^newbb/thread-(d+)-(d+)-(w*)-(ASC|DESC)-(next|prev).html$ modules/newbb/viewtopic.php?viewmode=$3&order=$4&topic_id=$1&forum=$2&move=$5
RewriteRule ^newbb/index-(d+).html$ modules/newbb/index.php?cat=$1
RewriteRule ^newbb/(w+).php.*$ modules/newbb/$1.php$2

#news
RewriteRule ^news/(d+).html$ modules/news/article.php?storyid=$1
RewriteRule ^news/index-(d+).html$ modules/news/index.php?storytopic=$1
RewriteRule ^news/index-(d+)-(d+).html$ modules/news/index.php?storytopic=$1&start=$2
RewriteRule ^news/ratenews-(d+).html$ modules/news/ratenews.php?storyid=$1
RewriteRule ^news/comment-(w*)-(d+)-(d+).html$ modules/news/comment_new.php?com_itemid=$2&com_order=$3&com_mode=$1

#extgallery
RewriteRule ^extgallery/index-(d+).html$ modules/extgallery/public_album.php?id=$1
RewriteRule ^extgallery/index-(d+)-(d+).html$ modules/extgallery/public_album.php?id=$1&start=$2
RewriteRule ^extgallery/photo-(d+).html(#?[a-zA-Z0-9]*)$ modules/extgallery/public_photo.php?photoId=$1$2
RewriteRule ^extgallery/userphoto-(d+).html(#?[a-zA-Z0-9]*)$ modules/extgallery/public_userphoto.php?photoId=$1$2
RewriteRule ^extgallery/rate-(d+)-(d+).html$ modules/extgallery/public_rating.php?id=$1&rate=$2
RewriteRule ^extgallery/useralbum-(d+).html$ modules/extgallery/public_useralbum.php?id=$1
RewriteRule ^extgallery/download-(d+).html$ modules/extgallery/public_download.php?id=$1
RewriteRule ^extgallery/sendecard-(d+).html$ modules/extgallery/public_sendecard.php?id=$1

rewrite_url.php

<?php
// $Id: rewrite_url.php,v 1.0 2009-3-16 cfc4n $
// <http://www.xoops.org.cn>
//
if (!defined("XOOPS_ROOT_PATH") || !defined("XOOPS_URL") ) {
    exit();
}
######################################
#正则表达式里好多代码都被高亮插件执行了,大家还是下载附件吧#
######################################

附件:xoops-rewrite-url

CNXCT小组的博客 is Stephen Fry proof thanks to caching by WP Super Cache