我使用Apache作为反向代理。专用服务器本身没有Web内容。如果客户端请求本地Apache服务器上的资源,Apache应确定该资源存在于哪个远程(代理)服务器上,并对该服务器执行代理重写。
一个片段(当前不起作用)应该演示,我会做什么:
RewriteCond http://200.202.204.11:3000%{REQUEST_URI} -U
RewriteRule ^(.*)$ http://200.202.204.11:3000$1 [P]
我放弃了我的其余配置(ProxyPass,ProxyPassReverse,其他RewriteCond,......)来专注于我的问题:
如何在重写之前检查外部资源是否存在?
RewriteCond的 -U 选项返回al。 -F 选项返回alwas false。我的意图是否有可行的解决方案?
答案 0 :(得分:0)
在寻找解决方案数周之后,我得出结论:如果存在外部资源,则没有可靠的RewriteRule。
如果您通过子域在反向代理服务器后面解决您的服务,那么您会好得多。例如。 'gitlab.youdomain.net'如果你想在你的反向代理后面的gitlab服务器上解决一个资源。因此,如果资源位于gitlab服务器的根目录“/”中,则反向代理不会混淆。
答案 1 :(得分:0)
我有同样的问题但是,据我所知,我得到了相同的结果:不可能只使用Apache httpd指令(至少使用2.2版本)。
在我的解决方案中,我使用RewriteMap和PHP脚本来检查外部资源是否存在。
在此示例中,当新请求到来时,RewriteMap会检查服务器A上是否存在请求的路径,如果成功找到,则会在同一服务器上反向代理请求。 另一方面,如果在服务器A上找不到请求的路径,它会实现重写规则以反向代理服务器B上的请求。
如上所述,我使用了RewriteMap
MapType
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]
这是一个有趣且棘手的部分。
这是由Apache执行的url_exists.php
脚本。它正在等待标准输入流并写入标准输出。
如果找到并可读资源,此脚本将返回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";
}
}