本文描述了RewriteMap
指令的使用,并提供了各种RewriteMap
类型的示例。
RewriteMap
指令定义了一个外部函数,可以在RewriteRule
或RewriteCond
指令的上下文中调用它来执行过于复杂的重写,或者太专业化而不能仅通过正则表达式执行。
RewriteMap
指令的语法如下:
RewriteMap MapName MapType:MapSource
映射名称是您为映射指定的任意名称,稍后将在指令中使用该名称。参数通过以下语法传递给映射:
${ MapName : LookupKey }
${ MapName : LookupKey | DefaultValue }
当发生这样的构造时,查询映射MapName
并查找LookupKey
键。如果找到此键,则map-function
构造将由SubstValue
替换。如果未找到键,则如果未指定DefaultValue
,则将其替换为DefaultValue
或空字符串。
例如,可以将RewriteMap
定义为:
RewriteMap examplemap "txt:/path/to/file/map.txt"
然后,可以在RewriteRule
中使用此映射,如下所示:
RewriteRule "^/ex/(.*)" "${examplemap:$1}"
如果在映射中找不到任何内容,则可以指定默认值:
RewriteRule "^/ex/(.*)" "${examplemap:$1|/not_found.html}"
int
:内部函数
当使用int
的MapType
时,MapSource
是可用的内部RewriteMap
函数之一。模块作者可以通过使用ap_register_rewrite_mapfunc
API注册它们来提供其他内部函数。默认提供的功能是:
toupper
:将键全部转换为大写。tolower
:将键全部转换为小写。escape
:将键中的特殊字符转换为十六进制编码。unescape
:将键中的十六进制编码转换回特殊字符。
将URI
重定向到自身的全小写版本 -
RewriteMap lc int:tolower
RewriteRule "(.*)" "${lc:$1}" [R]
txt
:纯文本映射
当使用txt
的MapType
时,MapSource
是纯文本映射文件的文件系统路径,每行包含一个以空格分隔的键/值对。可选地,一行可以包含以#
字符开头的注释。
有效的文本重写映射文件具有以下语法:
# Comment line
MatchingKey SubstValue
MatchingKey SubstValue # comment
调用RewriteMap
时,将在行的第一个参数中查找参数,如果找到则返回替换值。
例如,可以使用mapfile
将产品名称转换为产品ID
,以便更容易记住URL
,使用以下配方:
产品到ID配置如下 -
RewriteMap product2id "txt:/etc/apache2/productmap.txt"
RewriteRule "^/product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]
rnd
:随机化纯文本
当使用Rnd
的MapType
时,MapSource
是纯文本映射文件的文件系统路径,每行包含一个键,一个或多个值以|分隔。如果键匹配,将随机选择其中一个值。
例如,您可以使用以下映射文件和指令通过反向代理在多个后端服务器之间提供随机负载平衡。图像被发送到“静态”池中的一个服务器,而其他所有内容都被发送到“动态”池中的一个。
Rewrite map file
##
## map.txt -- rewriting map
##
static www1|www2|www3|www4
dynamic www5|www6
配置的指令如下 -
RewriteMap servers "rnd:/path/to/file/map.txt"
RewriteRule "^/(.*\.(png|gif|jpg))" "http://${servers:static}/$1" [NC,P,L]
RewriteRule "^/(.*)" "http://${servers:dynamic}/$1" [P,L]
因此,当请求图像并且第一个规则匹配时,RewriteMap
会在map
文件中查找字符串static
,它会随机返回一个指定的主机名,然后在RewriteRule
目标中使用。
如果希望更有可能选择其中一个服务器(例如,如果其中一个服务器的内存多于其他服务器,因此可以处理更多请求),只需在映射文件中列出更多次。
static www1|www1|www2|www3|www4
dbm
:DBM哈希文件
当使用dbm
的MapType
时,MapSource
是DBM
数据库文件的文件系统路径,该文件包含要在映射中使用的键/值对。这与txt映射的工作方式完全相同,但速度要快得多,因为DBM
是索引的,而文本文件则不是。这允许更快速地访问所需的密钥。
可以选择指定特定的dbm
类型:
RewriteMap examplemap "dbm=sdbm:/etc/apache/mapfile.dbm"
类型可以是sdbm,gdbm,ndbm
或db
。但是,建议您只使用Apache HTTP Server
提供的httxt2dbm
实用程序,因为它将使用正确的DBM
库,与构建httpd
本身时使用的库匹配。
要创建dbm
文件,请首先按照txt
部分中的说明创建文本映射文件。然后运行httxt2dbm
:
$ httxt2dbm -i mapfile.txt -o mapfile.map
然后,可以在RewriteMap
指令中引用生成的文件:
RewriteMap mapname "dbm:/etc/apache/mapfile.map"
prg
:外部重写程序
当使用prg
的MapType
时,MapSource
是可执行程序的文件系统路径,该程序将提供映射行为。这可以是编译的二进制文件,也可以是Perl
或Python
等解释语言的程序。
当Apache HTTP Server
启动时,该程序启动一次,然后通过STDIN
和STDOUT
与重写引擎通信。也就是说,对于每个映射函数查找,它通过STDIN
期望一个参数,并且应该在STDOUT
上返回一个新行终止的响应字符串。如果没有相应的查找值,则映射程序应返回四个字符的字符串“NULL
”以指示此情况。
如果在没有将RewriteEngine
设置为on
的上下文中定义外部重写程序,则不会启动外部重写程序。
默认情况下,外部重写程序作为用户:启动httpd
的组运行。这可以在UNIX
系统上通过将用户名和组名作为第三个参数以username:groupname
格式传递给RewriteMap
来更改。
此功能使用重写映射互斥锁,这是与程序可靠通信所必需的。可以使用Mutex
指令配置互斥锁机制和锁定文件。
这里显示了一个简单的示例,它将替换请求URI
中带下划线的所有破折号。
重写配置如下 -
RewriteMap d2u "prg:/www/bin/dash2under.pl" apache:apache
RewriteRule "-" "${d2u:%{REQUEST_URI}}"
dash2under.pl
#!/usr/bin/perl
$| = 1; # Turn off I/O buffering
while (<STDIN>) {
s/-/_/g; # Replace dashes with underscores
print $_;
}
dbd
或fastdbd
:SQL查询
使用dbd
或fastdbd
的MapType
时,MapSource
是一个SQL SELECT
语句,它接受单个参数并返回单个值。
需要将mod_dbd
配置为指向正确的数据库以执行此语句。
这种MapType
有两种形式。使用dbd
的MapType
会导致查询与每个映射请求一起执行,而使用fastdbd
会在内部缓存数据库查找。因此,虽然fastdbd
更高效,因此更快,但在重新启动服务器之前,它不会接受对数据库的更改。
如果查询返回多行,则使用结果集中的随机行。
示例:
RewriteMap myquery "fastdbd:SELECT destination FROM rewrite WHERE source = %s"