Я реализовал обратный прокси-сервер с Apache httpd 2.2, но это невозможно сделать он использует только директивы apache. Поэтому мне пришлось использовать простой скрипт PHP, чтобы проверить существование удаленного URL.
Когда приходит новый запрос, он проверяет наличие текущего пути на сервере 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]
Здесь начинается интересная и сложная часть.
Это сценарий url_exists.php
, выполняемый Apache. Он ожидает стандартного входного потока и записывает в стандартный выходной поток.
Эти сценарии возвращают 1
, если ресурс найден и доступен для чтения, в противном случае 0
.
На самом деле это довольно просто, потому что он реализует только HTTP-запрос с использованием метода HEAD.
<?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";
error_log($line. " ".$str);
echo $str."\n";
} else {
error_log('empty line!');
}
}
Чтобы проверить наличие удаленных ресурсов в RewriteCond, вы можете использовать следующее:
'- U' (существующий URL-адрес, через подзапрос) Проверяет, действительно ли TestString - действительный URL-адрес, доступный через все серверные настроенные в настоящее время средства управления доступом для этого пути. Это использует внутренний подзапрос на выполнение проверки, поэтому используйте его с осторожностью - он может повлиять на производительность вашего сервера!
Я никогда не использовал его лично. Но это работает как проверка существования файла и тому подобное.
Затем у вас может быть RewriteRule, которое проксирует запрос (опция [P]).