Mod rewrite 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

我使用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选项为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";
    }
}