Mod rewrite Apache:如果存在外部资源,只需重写即可
我使用Apache作为反向代理。专用服务器本身没有web内容。如果客户端请求本地Apache服务器上的资源,Apache应确定该资源存在于哪个远程(代理)服务器上,并对该服务器执行代理重写 一个片段(目前不起作用)应该演示我将做什么:Mod rewrite Apache:如果存在外部资源,只需重写即可,mod-rewrite,url-rewriting,apache2,apache,reverse-proxy,Mod Rewrite,Url Rewriting,Apache2,Apache,Reverse Proxy,我使用Apache作为反向代理。专用服务器本身没有web内容。如果客户端请求本地Apache服务器上的资源,Apache应确定该资源存在于哪个远程(代理)服务器上,并对该服务器执行代理重写 一个片段(目前不起作用)应该演示我将做什么: RewriteCond http://200.202.204.11:3000%{REQUEST_URI} -U RewriteRule ^(.*)$ http://200.202.204.11:3000$1
RewriteCond http://200.202.204.11:3000%{REQUEST_URI} -U
RewriteRule ^(.*)$ http://200.202.204.11:3000$1 [P]
我省去了其余的配置(ProxyPass、ProxyPassReverse、其他RewriteCond…)来关注我的问题:
如何在重写之前检查外部资源是否存在/可用?
RewriteCond返回值的-U选项为true。-F选项返回alwas false。对于我的意图,是否有一个有效的解决方案?经过数周的搜索,我得出结论:如果存在外部资源,则没有可靠的重写规则
如果您通过子域在反向代理后面寻址服务,您会做得更好。例如,“gitlab.youdomain.net”,如果要在反向代理后面的gitlab服务器上寻址ressource。因此,如果ressource位于gitlab服务器的根目录“/”中,则反向代理不会变得混乱。我遇到了相同的问题,但据我所知,我得到了相同的结果:仅使用Apache httpd指令是不可能的(至少在版本2.2中)。
在我的解决方案中,我使用了一个重写映射和一个能够检查外部资源是否存在的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\u 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";
}
}