Назад | Перейти на главную страницу

Может ли условие перезаписи 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 (Источник), в данном случае http вместо https.

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

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

Ниже приведен код, который у меня есть. И предварительное условие, и перезапись заголовка работают нормально. Однако это условие вызывает ошибку 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>

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