У меня есть ProxyPass, настроенный для достижения следующего: На моем сервере я запускаю службу, которая обеспечивает прослушивание Rest-API через порт 7777. Со стороны клиента я хочу иметь возможность вызывать этот API следующим образом: http://example.org/servicename/PARAMETER
Полный вызов этого API должен выглядеть так: HTTP PUT @ http://example.org/servicename/PARAMETER
(где PARAMETER
это какая-то строка). Внутренне это должно переводиться на следующий URL: http://server.ip:7777/servicename/PARAMETER
Все работает так, как ожидалось, пока ПАРАМЕТР не (!) Так: http://parameter.org
(на самом деле мне нужно кодировать URL: http%3A%2F%2Fparameter.org
). Итак, в общем, звонок http://example.org/servicename/http%3A%2F%2Fparameter.org
В http://
в параметре сбивает с толку apache, что приводит к следующему сообщению об ошибке в ответе на вызов:
!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /servicename/http://parameter.org was not found on this server.</p>
<hr>
<address>Apache/2.2.22 (Debian) Server at example.org Port 80</address>
</body></html>
Если я заменю http%3A%2F%2Fparameter.org
с, например, test
, все работает как надо. Как-то http://
в параметре смущает apache. Есть ли способ позволить apache игнорировать это?
Моя текущая конфигурация этого виртуального хоста выглядит так:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/example
ServerName example.org
ErrorLog /var/log/apache2/example_error.log
LogLevel warn
CustomLog /var/log/apache2/example_access.log combined
<IfModule mod_proxy.c>
ProxyRequests Off
ProxyPass / http://localhost:7777/
ProxyPassReverse / http://localhost:7777/
</IfModule>
</VirtualHost>
Предпосылки:
Изменить 1:
tail -f /var/log/apache2/example_access.log
дает
128.xxx.xxx.xxx - - [19/Aug/2015:16:53:17 +0200] "PUT /servicename/http%3A%2F%2Fparameter.org HTTP/1.1" 404 521 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36"
В конфигурации Apache по умолчанию AllowEncodedSlashes директива установлена на выключен. Это означает, что: "... Директива AllowEncodedSlashes позволяет использовать URL-адреса, содержащие закодированные разделители путей [...] в информации о пути. При значении по умолчанию Off, такие URL-адреса отклоняются с ошибкой 404 (Not found).. ..."
Итак, проблема в том, что mod_proxy не проксирование ваших запросов POST на основе URL-адресов, поскольку Apache их отклоняет (с кодом 404) до того, как mod_proxy предпримет действия.
Другая возможная проблема связана с процессом кодирования URL: ваш apache (внешний интерфейс) обязательно получит строку с правильной кодировкой URL (ту, которую вы ему отправляете: http://example.org/servicename/http%3A%2F%2Fparameter.org ), и я ожидаю, что он (apache) будет декодировать его URL-адрес во время внутренней обработки связанного запроса POST. Поэтому я ожидаю, что mod_proxy внутри Apache получит реальный URL (не закодированный), и мне интересно, будет ли он при проксировании выполнять цикл с кодировкой URL. На официальная документация ProxyPass Я вижу: "Обычно mod_proxy канонизирует URL-адреса ProxyPassed. Но это может быть несовместимо с некоторыми бэкэндами, особенно теми, которые используют PATH_INFO. Необязательное ключевое слово nocanon подавляет это и передает "необработанный" URL-путь на бэкэнд. Обратите внимание, что это ключевое слово может повлиять на безопасность вашей серверной части, поскольку оно снимает обычную ограниченную защиту от атак на основе URL-адресов, предоставляемую прокси-сервером.", поэтому вам следует также оценить использование опции" nocanon ".
Оба выпуска (AllowEncodedSlashes и ноканон) были упомянуты в этот вопрос StackOverflow
Я думаю, что у него такое поведение, потому что в http://
в /
по-прежнему рассматривается как разделитель каталогов. Таким образом, вы ищете ресурс paramater.org
в папке http:
(под папкой я на самом деле не имею в виду настоящую папку, поскольку это может быть просто путь доступа, но вы можете понять).
Я не думаю, что ты умеешь писать /
для ресурса в URL-адресе, поэтому вам нужно использовать% 2F