Я пытаюсь сравнить две переменные сервера как часть условия перезаписи URL. Но сначала немного контекста...
В IIS, если вы запрашиваете http://www.example.com/foo
и foo
является каталогом, IIS отправляет перенаправление 302 «Объект перемещен» http://www.example.com/foo/
в качестве «вежливого перенаправления» (Источник).
Если вы используете IIS+ARR в качестве обратного прокси-сервера с разгрузкой SSL, запрос, который получает внутренний узел IIS, передается по протоколу http, а не https.
Объедините эти два поведения, и любезные перенаправления IIS отключат SSL. В любезном перенаправлении используется та же схема, что и в запросе, полученном IIS (Источник), в данном случае http вместо https.
Я хотел бы создать исходящее правило перезаписи, которое будет сравнивать входящий URL с исходящим заголовком Location и переписывать его с http на https в этом случае:
- Ответ — перенаправление:
{RESPONSE_STATUS}
302 - Входящий запрос был через SSL:
{HTTPS}
"включено" - Входящий URL не заканчивается косой чертой.
- Исходящий заголовок Location заканчивается косой чертой.
Все вышеперечисленное обрабатывается в предусловии. Сложность в последней части:
- Путь исходящего заголовка Location совпадает с путем входящего URL-адреса с добавлением косой черты.
Ниже приведен код, который у меня есть на данный момент. Предварительное условие и перезапись заголовка работают нормально. Однако условие вызывает ошибку 500 (ошибка модуля URL Rewrite), предположительно из-за того, что я использую {REQUEST_URI}
в шаблоне. Я пробовал разделить условие на два и использовать группы захвата, но это тоже не сработало. Есть идеи?
<rule name="Fix: Courtesy Redirect + SSL Offloading = SSL dropped" preCondition="Courtesy Redirect Drops SSL" enabled="true">
<match serverVariable="RESPONSE_LOCATION" pattern="^http://(.+/)$" />
<conditions>
<add input="{RESPONSE_LOCATION}" pattern="{REQUEST_URI}/" />
</conditions>
<action type="Rewrite" value="https://{R:1}" />
</rule>
<preConditions>
<preCondition name="Courtesy Redirect Drops SSL">
<add input="{RESPONSE_STATUS}" pattern="^302$" />
<add input="{HTTPS}" pattern="^on$" />
<add input="{REQUEST_URI}" pattern=".*[^/]$" />
<add input="{RESPONSE_LOCATION}" pattern="^http://.+/$" />
</preCondition>
</preConditions>
решение1
Вы можете использоватьпоставщик услуг индивидуальной перезаписи.Поставщик — это код C#, который преобразует одну строку в другую. Затем вы можете использовать его аналогично тому, как вы используете rewrite map:
Вы можете выбрать разделитель, который вообще недопустим в URL. (Возможно, используйте пробел или что-то в этом роде. Я буду использовать |
его, чтобы он был виден в этом посте, но вам следует выбрать какую-то другую строку.)
Вы напишете правило для установки значения переменной сервера IsItMatching
. Значение переменной сервера будет установлено с помощью вашего поставщика перезаписи URL:
{provider_name:{server_variable_1}|{server_variable_2}}
Код C#, реализующий поставщик, затем выполнит следующее (псевдокод, без проверки ошибок):
string Rewrite(string input)
{
string[] inputVariables = input.split(separator);
if (inputVariables[0] == inputVariables[1] + "/")
return "yes";
else
return "no";
}
Затем вы напишете еще одно правило для проверки того, является ли значение серверной IsItMatching
переменной «да» или «нет».