使用 RewriteMap
它描述了RewriteMap
伪指令的用法,并提供了RewriteMap
各种类型的示例。
请注意,这些示例中的许多示例在您的特定服务器配置中都不会起作用,因此,理解它们,而不只是将示例剪切并粘贴到您的配置中,这一点很重要。
介绍
该RewriteMap
指令定义可以在的上下文中调用外部函数RewriteRule
或RewriteCond
指令来执行重写是太复杂,或过专用于只由正则表达式来执行。查找的来源可以是以下各节中列出的任何类型,并且可以在RewriteMap
参考文档中进行枚举。
该RewriteMap
指令的语法如下:
RewriteMap MapName MapType:MapSource
该MAPNAME是一个任意名称分配给图,您将在指令以后使用。参数通过以下语法传递给地图:
${
MapName:
LookupKey}
${
MapName:
LookupKey|
DefaultValue}
当发生这种构造时,将查询映射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}"
每个目录和.htaccess上下文
该RewriteMap
指令不能在<Directory>
节或.htaccess
文件中使用。您必须在服务器或虚拟主机上下文中声明映射。您可以在这些作用域的RewriteRule
和RewriteCond
指令中使用映射(一旦创建)。您只是不能在这些范围内声明它。
以下各节描述了可以使用的各种MapType,并给出了每个示例。
int:内部函数
使用MapType int
为时,MapSource是可用的内部RewriteMap
函数之一。模块作者可以通过向ap_register_rewrite_mapfunc
API 注册来提供其他内部功能。默认情况下提供的功能是:
- toupper:
将密钥转换为全部大写。 - tolower:
将密钥转换为所有小写字母。 - escape:
将密钥中的特殊字符转换为十六进制编码。 - unescape:
将密钥中的十六进制编码转换回特殊字符。
要使用这些功能之一,请创建一个RewriteMap
引用int函数,然后在您的中使用它RewriteRule
:
将URI重定向到自身的全小写版本
RewriteMap lc int:tolower RewriteRule "(.*)" "${lc:$1}" [R]
请注意,此处提供的示例仅用于说明目的,而不是建议。如果要使URL不区分大小写,请考虑使用mod_speling
代替。
txt:纯文本地图
使用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文件
给出的示例旨在用于服务器或虚拟主机范围。如果您打算在.htaccess
文件中使用它,则需要从重写模式中删除前导斜杠以使其与任何内容匹配:RewriteRule "^product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]
缓存的查询
查找的密钥由httpd缓存,直到映射文件的mtime
(修改时间)更改,或者重新启动httpd服务器。这样可确保在许多请求调用的地图上具有更好的性能。
rnd:随机纯文本
当使用MapType rnd
为时,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
查找字符串static
,该字符串随机返回指定的主机名之一,然后在RewriteRule
目标中使用该主机名。
如果您希望选择其中一台服务器的可能性更大(例如,如果其中一台服务器比其他服务器具有更多的内存,因此可以处理更多请求),只需在映射文件中将其列出更多次即可。
static www1|www1|www2|www3|www4
dbm:DBM哈希文件
当使用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服务器。这样可确保在许多请求调用的地图上具有更好的性能。
prg:外部重写程序
使用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 $_; }
警告!
- 使您的重写映射程序尽可能简单。如果程序挂起,它将导致httpd无限期地等待来自映射的响应,从而导致httpd停止响应请求。
- 确保关闭程序中的缓冲。在Perl中,这是通过示例脚本的第二行完成的:
$|= 1;
当然,这在其他语言中也会有所不同。缓冲的I / O将使httpd等待输出,因此它将挂起。 - 请记住,只有在服务器启动时才启动该程序的一个副本。所有请求都需要克服这一瓶颈。如果许多请求必须经过此过程,或者脚本本身非常慢,则这可能会导致严重的速度下降。
dbd或fastdbd:SQL查询
当使用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>