本文档是mod_rewrite
参考文档的补充。它描述了RewriteMap
伪指令的用法,并提供了RewriteMap
各种类型的示例。
该RewriteMap
指令定义可以在的上下文中调用外部函数
RewriteRule
或
RewriteCond
指令来执行重写是太复杂,或过专用于只由正则表达式来执行。查找的来源可以是以下各节中列出的任何类型,并且可以在RewriteMap
参考文档中进行枚举。
该RewriteMap
指令的语法如下:
RewriteMap MapName MapType:MapSource
该MAPNAME是一个任意名称分配给图,您将在指令以后使用。参数通过以下语法传递给地图:
${
MapName :
LookupKey
}
${
MapName :
LookupKey |
默认值 }
当发生这种构造时,将查询映射MapName并查找键LookupKey。如果找到了键,则将map-function构造替换为 SubstValue。如果未找到该密钥然后它被取代的默认值或由空字符串,如果没有默认值被指定。
例如,您可以将定义
RewriteMap
为:
RewriteMap examplemap "txt:/path/to/file/map.txt"
然后,您将可以按以下方式使用此地图
RewriteRule
:
RewriteRule "^/ex/(.*)" "${examplemap:$1}"
如果在地图中找不到任何内容,则可以指定默认值:
RewriteRule "^/ex/(.*)" "${examplemap:$1|/not_found.html}"
该RewriteMap
指令不能在<Directory>
节或
.htaccess
文件中使用。您必须在服务器或虚拟主机上下文中声明映射。您可以在这些作用域的RewriteRule
和
RewriteCond
指令中使用映射(一旦创建)。您只是不能在这些范围内声明它。
以下各节描述了可以使用的各种MapType,并给出了每个示例。
当使用MapType int
为时,MapSource是可用的内部RewriteMap
函数之一。模块作者可以通过向ap_register_rewrite_mapfunc
API 注册来提供其他内部功能
。默认情况下提供的功能是:
要使用这些功能之一,请创建一个RewriteMap
引用int函数,然后在您的中使用它RewriteRule
:
将URI重定向到自身的全小写版本
RewriteMap lc int:tolower RewriteRule "(.*)" "${lc:$1}" [R]
请注意,此处提供的示例仅用于说明目的,而不是建议。如果要使URL不区分大小写,请考虑使用
mod_speling
代替。
当使用MapType txt
为时,MapSource是纯文本映射文件的文件系统路径,每行包含一个以空格分隔的键/值对。可选地,一行可以包含以“#”字符开头的注释。
有效的文本重写映射文件将具有以下语法:
# Comment line
MatchingKey SubstValue
MatchingKey SubstValue # comment
当RewriteMap
被调用的自变量是在一行的第一个参数寻找,并且,如果找到,则返回替代值。
例如,我们可以使用以下配方使用映射文件将产品名称转换为易于识别的URL的产品ID:
产品到ID的配置
RewriteMap product2id "txt:/etc/apache2/productmap.txt" RewriteRule "^/product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]
我们在这里假设prods.php
脚本收到id=NOTFOUND
在查找映射中找不到产品的参数时知道该怎么办。
/etc/apache2/productmap.txt
然后,该文件包含以下内容:
##
## productmap.txt - Product to ID map file
##
television 993
stereo 198
fishingrod 043
basketball 418
telephone 328
因此,在http://example.com/product/television
被请求时,将RewriteRule
应用,并将请求在内部映射到/prods.php?id=993
。
.htaccess
文件中使用它,则需要从重写模式中删除前导斜杠以使其与任何内容匹配:
RewriteRule "^product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]
查找的密钥由httpd缓存,直到映射文件的mtime
(修改时间)更改,或者重新启动httpd服务器。这样可确保在许多请求调用的地图上具有更好的性能。
当使用MapType rnd
为时,MapSource是纯文本映射文件的文件系统路径,该文件的每一行都包含一个键以及一个或多个以分隔的值|
。如果密钥匹配,将随机选择这些值之一。
例如,您可以使用以下映射文件和指令通过反向代理在多个后端服务器之间提供随机负载平衡。图像发送到“静态”池中的一台服务器,而其他所有内容都发送到“动态”池中的一台。
##
## 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
查找字符串static
,该字符串
随机返回指定的主机名之一,然后在RewriteRule
目标中使用该主机名
。
如果您希望选择其中一台服务器的可能性更高(例如,如果其中一台服务器比其他服务器具有更多的内存,因此可以处理更多请求),只需在映射文件中将其列出更多次即可。
static www1|www1|www2|www3|www4
使用MapType dbm
为时,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"
请注意,对于某些dbm类型,将生成多个文件,并且具有通用的基本名称。例如,您可能有两个名为mapfile.map.dir
和的文件
mapfile.map.pag
。这是正常现象,您只需要mapfile.map
在RewriteMap
指令中使用基本名称即可。
查找的密钥由httpd缓存,直到映射文件的mtime
(修改时间)更改,或者重新启动httpd服务器。这样可确保在许多请求调用的地图上具有更好的性能。
使用MapType时prg
,MapSource是可执行程序的文件系统路径,该程序将提供映射行为。这可以是已编译的二进制文件,也可以是解释语言(例如Perl或Python)的程序。
启动Apache HTTP Server时,该程序将启动一次,然后通过STDIN
和与重写引擎进行通信
STDOUT
。也就是说,对于每个map函数查找,它都需要通过传递一个参数STDIN
,并应在上返回一个换行符终止的响应字符串
STDOUT
。如果没有相应的查找值,则映射程序应返回四个字符的字符串“ NULL
”来表明这一点。
如果外部重写程序是在未RewriteEngine
设置为
的上下文中定义的,则不会启动它们on
。
默认情况下,外部重写程序以启动httpd的user:group运行。在UNIX系统上,可以通过将用户名和组名作为第三个参数传递RewriteMap
给
username:groupname
格式来更改此名称
。
此功能利用了rewrite-map
互斥锁,这是与程序进行可靠通信所必需的。互斥锁机制和锁定文件可以使用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 $_; }
$| = 1;
当然,这在其他语言中也会有所不同。缓冲的I / O将使httpd等待输出,因此它将挂起。当使用dbd
或的MapType时fastdbd
,MapSource是一个SQL SELECT语句,它使用单个参数并返回单个值。
mod_dbd
将需要配置为指向正确的数据库以执行此语句。
此MapType有两种形式。使用MapType时,dbd
将对每个映射请求执行查询,而使用时,则fastdbd
在内部缓存数据库查找。因此,虽然
fastdbd
效率更高,因此也更快,但在重新启动服务器之前,不会对数据库进行更改。
如果查询返回多行,则使用结果集中的随机行。
RewriteMap myquery "fastdbd:SELECT destination FROM rewrite WHERE source = %s"
查询名称将作为SQL预准备语句的标签传递给数据库驱动程序,因此将需要遵循数据库所需的任何规则(例如区分大小写)。
该RewriteMap
指令可以多次出现。对于每个映射功能,请使用一个RewriteMap
指令声明其重写映射文件
。
虽然无法在每个目录上下文(文件或
块)中声明映射,但可以在每个目录上下文中使用此映射。.htaccess
<Directory>