如何在PHP中使用Apache RewriteMap?

如何在PHP中使用Apache RewriteMap?,php,apache,.htaccess,mod-rewrite,url-rewriting,Php,Apache,.htaccess,Mod Rewrite,Url Rewriting,我一直在研究使用来动态处理一系列URL重写,我想做的是使用PHP脚本来生成适当的重写条件和规则——但我就是无法让它工作 我让Apache在Linux服务器上运行,带有WebHost Manager和cPanel 我在WHM>Apache配置>包含编辑器>虚拟主机包含>所有版本中添加了以下内容: RewriteMap myrules "prg:/usr/lib/php /path/to/my/script.php" 我更新了配置文件,Apache重启正常 现在我想调用从.htaccess文件定义

我一直在研究使用来动态处理一系列URL重写,我想做的是使用PHP脚本来生成适当的重写条件和规则——但我就是无法让它工作

我让Apache在Linux服务器上运行,带有WebHost Manager和cPanel

我在WHM>Apache配置>包含编辑器>虚拟主机包含>所有版本中添加了以下内容:

RewriteMap myrules "prg:/usr/lib/php /path/to/my/script.php"
我更新了配置文件,Apache重启正常

现在我想调用从.htaccess文件定义的重写映射来执行重写,但这就是我遇到的问题,一切似乎都崩溃了

我想获取传入的域,对照映射检查它,并返回相关的域:user\u name值。比如:

RewriteCond %{HTTP_HOST} ^(www\.)?${myrules:%{HTTP_HOST}}\.com$ [NC]
RewriteRule ^(.*)$ http://mywebsite.com/user/${myrules:%{HTTP_HOST}}/$1 [NC,P,L]
例如,如果我的地图上有johnsmith.com:johnsmith,那么传入的URL johnsmith.com将代理mywebsite.com/user/johnsmith/上的内容

首先,我很确定上面的条件/规则都错了。

让它正确是我的首要任务

其次,如何使用重写映射定义的PHP脚本输出映射?


任何帮助都将不胜感激

johnsmith.com是否首先解析到您的服务器?如果johnsmith.com和mywebsite.com由同一台服务器处理,则不需要代理请求

我认为你的规则应该更像这样:

RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+\.com)$ [NC]
RewriteRule ^.*$ http://mywebsite.com/user/${myrules:%1}/$0 [NC,P,L]
# or
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+\.com)$ [NC]
RewriteRule ^ - [E=MAPTO:${myrules:%1}]
RewriteCond %{ENV:MAPTO} !=""
RewriteRule ^.*$ http://mywebsite.com/user/%{ENV:MAPTO}/$0 [NC,P,L]
注:

  • $0
    是与重写规则模式匹配的整个字符串(如果.htaccess在DocumentRoot中,
    $0
    %{REQUEST\u URI}
    是相同的)
  • %1
    是与最后一个RewriteCond的第一个捕获括号匹配的字符串(因此,不带潜在前缀“www.”的主机头的值)
在第二组规则中,第一个规则将“RewriteMap调用”的结果放入名为MAPTO的环境变量中。第二个用于忽略未知/未映射的主机(MAPTO值为空字符串)

以及一个以重写图的形式演示PHP代码:

<?php
$map = [
    'foo.com' => 'bar',
    'johnsmith.com' => 'john-smith',
];

if (!defined('STDOUT'))
    define('STDOUT', fopen('php://stdout', 'w'));
if (!defined('STDIN'))
    define('STDIN', fopen('php://stdin', 'r'));
set_file_buffer(STDOUT, 0);
while (!feof(STDIN)) {
    $input = rtrim(fgets(STDIN), "\n");
    fputs(STDOUT, (array_key_exists($input, $map) ? $map[$input] : 'NULL') . "\n");
}

不要这样做。您有prg:example,但请先阅读注释:)
HTTP\u HOST
是服务器的主机名,而不是客户端的名称。有一些变量,但我不确定这些值有多可靠。请参阅一个小Perl示例的解释。@dusan.bajic其中的注释似乎建议重定向。不幸的是,我不能只是重定向,我需要代理。谢谢你的伟大的例子!你能解释一下第二套规则是怎么回事吗?另外,我希望能够匹配映射中的完整主机,例如johnsmith.com或johnsmith.net或sandbox.johnsmith.org。@实际上,为了与规则一致,我的代码示例中缺少域扩展。我还编辑了我的答案,添加了一些更多的信息。您的重写条件似乎只与.com匹配——其他扩展呢?非常好的帮助,谢谢。@HWD我保留了您最初的设计,这意味着一个“.com”扩展。但是,如果您希望匹配任何域,而不需要潜在的“www.”前缀,则可以使用
^(?:www\)?(.+)
。我相信PHP代码会给我带来错误。STDOUT/STDIN似乎作为字符串而不是资源返回。