我遇到了同样的问题,但据我所知,我得到了相同的结果:仅使用 Apache httpd 指令(至少使用 2.2 版)是不可能的。
在我的解决方案中,我使用 RewriteMap 和 PHP 脚本来检查外部资源是否存在。
在这个例子中,当一个新的请求到来时,RewriteMap 检查服务器 A 上请求的路径是否存在,如果成功找到,它将反向代理同一服务器上的请求。另一方面,如果在服务器 A 上没有找到请求的路径,它会执行一个重写规则来反向代理服务器 B 上的请求。
如前所述,我使用了一个RewriteMap
withMapType
prg:
和一个 PHP 脚本。这里是 Apache 指令:
# Please pay attention to RewriteLock
# this directive must be defined in server config context
RewriteLock /tmp/if_url_exists.lock
RewriteEngine On
ProxyPreserveHost Off
ProxyRequests Off
RewriteMap url_exists "prg:/usr/bin/php /opt/local/scripts/url_exists.php"
RewriteCond ${url_exists:http://serverA%{REQUEST_URI}} >0
RewriteRule . http://serverA%{REQUEST_URI} [P,L]
RewriteRule . http://serverB%{REQUEST_URI} [P,L]
这是有趣和棘手的部分。这是url_exists.php
由 Apache 执行的脚本。它正在等待标准输入流并写入标准输出。1
如果找到资源并且可读,则此脚本返回,否则返回0
. 它是如此的轻巧,因为它只使用 HEAD 方法实现了一个 HTTP 请求。
<?php
function check_if_url_exists($line) {
$curl_inst = curl_init($line);
curl_setopt( $curl_inst, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt( $curl_inst, CURLOPT_LOW_SPEED_LIMIT, 1);
curl_setopt( $curl_inst, CURLOPT_LOW_SPEED_TIME, 180);
curl_setopt( $curl_inst, CURLOPT_HEADER, true);
curl_setopt( $curl_inst, CURLOPT_FAILONERROR, true);
// Exclude the body from the output and request method is set to HEAD.
curl_setopt( $curl_inst, CURLOPT_NOBODY, true);
curl_setopt( $curl_inst, CURLOPT_FOLLOWLOCATION, true);
curl_setopt( $curl_inst, CURLOPT_RETURNTRANSFER, true);
$raw = curl_exec($curl_inst);
curl_close($curl_inst);
return ($raw != false) ? true : false;
}
set_time_limit(0);
$keyboard = fopen("php://stdin","r");
while (true) {
$line = trim(fgets($keyboard));
if (!empty($line)) {
$str = (check_if_url_exists($line)) ? "1" : "0";
echo $str."\n";
}
}