2

我使用 Apache 作为反向代理。专用服务器本身没有网页内容。如果客户端请求本地 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选项返回 alwas true。-F选项返回始终为false。我的意图是否有可行的解决方案?

4

2 回答 2

0

在搜索了数周以获得解决方案后,我得出结论:如果存在外部资源,则没有可靠的 RewriteRule。

如果您通过子域在反向代理后面处理您的服务,您会做得更好。例如“gitlab.youdomain.net”,如果你想在你的反向代理后面的 gitlab 服务器上处理资源。因此,如果资源位于 gitlab 服务器的根目录 '/' 中,反向代理不会变得混乱。

于 2012-11-08T09:41:29.710 回答
0

我遇到了同样的问题,但据我所知,我得到了相同的结果:仅使用 Apache httpd 指令(至少使用 2.2 版)是不可能的。
在我的解决方案中,我使用 RewriteMap 和 PHP 脚本来检查外部资源是否存在。

在这个例子中,当一个新的请求到来时,RewriteMap 检查服务器 A 上请求的路径是否存在,如果成功找到,它将反向代理同一服务器上的请求。另一方面,如果在服务器 A 上没有找到请求的路径,它会执行一个重写规则来反向代理服务器 B 上的请求。

如前所述,我使用了一个RewriteMapwithMapType 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";
    }
}
于 2013-05-20T10:18:56.570 回答