Может ли условие перезаписи URL сравнить две серверные переменные?

Я пытаюсь сравнить две серверные переменные как часть условия перезаписи URL. Но сначала немного контекста...

В IIS, если вы запрашиваете http://www.example.com/foo а также foo является каталогом, IIS отправляет 302 перенаправление "Объект перемещен" в http://www.example.com/foo/ как "перенаправление вежливости" ( источник).

Если вы используете IIS+ARR в качестве обратного прокси-сервера с разгрузкой SSL, запрос, который получает внутренний узел IIS, выполняется через http, а не через https.

Объедините эти два поведения, и любезные перенаправления IIS отбрасывают SSL. Перенаправление вежливости использует ту же схему, что и запрос, полученный IIS ( Source), в данном случае http вместо https.

Я хотел бы создать правило исходящей перезаписи, которое будет сравнивать входящий URL-адрес с исходящим заголовком Location и переписывать его с http на https в этом случае:

  • Ответ - редирект: {RESPONSE_STATUS} это 302
  • Входящий запрос был через SSL: {HTTPS} включен
  • Входящий URL не заканчивается косой чертой.
  • Исходящий заголовок Location заканчивается косой чертой.

Все вышеперечисленное обрабатывается в предварительном условии. Сложная часть - последний бит:

  • Путь к исходящему заголовку Location совпадает с входящим URL-адресом с добавленной косой чертой.

Ниже приведен код, который у меня есть. Предварительное условие и перезапись заголовка работают нормально. Однако это условие вызывает ошибку 500 (ошибка модуля перезаписи URL), возможно потому, что я использую {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#, который превращает одну строку в другую. Затем вы можете использовать его аналогично тому, как вы использовали бы карту перезаписи:

Вы можете выбрать разделитель, который вообще недействителен в 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 Переменная сервера - "да" или "нет".

Другие вопросы по тегам