Коллеги, приветствую! В этой статье мы поговорим о том, что происходит под капотом компонента URL Rewrite для IIS для целей диагностики. Разобравшись в этом вопросе на практике, мы сможем понять работу механизма, его логику, а также мы поймем как создавать правила таким образом, чтобы они не мешали работе друг друга. Вопрос необходимости проведения диагностики URL Rewrite будет становиться все более острым по мере возникновения дополнительных правил, а также по мере роста сложности этих самых правил.

Эта статья представляет собой перевод официальной документации Microsoft с добавлением небольших изменений от автора. Оригинальная статья доступна — здесь.

Подготовка тестового стенда

Разворачиваем виртуальную машину

Для целей тестирования предлагаю создать небольшой тестовый стенд из одной виртуальной машины. Для автоматизации этого процесса можно скачать или склонировать репозиторий на GitHub и выполнить предварительные шаги по установке.

Когда все будет готово, перейти в папку сценария Localhost_1.0 и выполнить команду:

vagrant up

Тестовый стенд будет развернут автоматически, пока что можно выпить чашечку чая или кофе. Конечно, вам никто не мешает развернуть это любым другим удобным способом.

Спустя время, виртуальная машина на базе Windows Server 2019 будет готова и мы сможем подключиться к ней либо через менеджер виртуальных машин VirtualBox, либо при помощи подключения RDP клиента по адресу 127.0.0.1:33389.

В качестве учетной записи для подключения указываем — Administrator. Пароль — vagrant.

Разворачиваем IIS

Переходим в процессу развертывания IIS.

После успешного входа в систему, запускаем Powershell от имени администратора и выполняем следующую команду:

Install-WindowsFeature -name Web-Server, Web-Http-Tracing, Web-ASP, Web-Asp-Net45, Web-Asp-Net45  -IncludeManagementTools

После ее выполнения мы увидим сообщение об успешности установки указанных компонентов.

Также мы можем убедиться в том, что сервер IIS запущен и работает корректно. Для этого откроем браузер и перейдем по адресу http://localhost/.

Устанавливаем URL Rewrite

Теперь займемся установкой компонента URL Rewrite. Для этого переходим на эту страницу, скачиваем и устанавливаем модуль. После его инсталляции в диспетчере IIS появится раздел URL Rewrite.

Поздравляю, нам удалось развернуть тестовый стенд и установить необходимые компоненты. Теперь мы готовы к изучению механизма работы компонента URL Rewrte.

Создание тестовой станицы и простых правил

Как мы уже проверяли ранее, при обращении к сайту IIS, возвращается страница iisstart.html. Давайте создадим отдельную тестовую страницу. Для этого переходим в каталог %SystemDrive%\inetpub\wwwroot\ и создадим файл article.aspx со следующим содержанием:

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>URL Rewrite Module Test</title>
</head>
<body>
      <h1>URL Rewrite Module Test Page</h1>
      <table>
            <tr>
                  <th>Server Variable</th>
                  <th>Value</th>
            </tr>
            <tr>
                  <td>Original URL: </td>
                  <td><%= Request.ServerVariables["HTTP_X_ORIGINAL_URL"] %></td>
            </tr>
            <tr>
                  <td>Final URL: </td>
                  <td><%= Request.ServerVariables["SCRIPT_NAME"] + "?" + Request.ServerVariables["QUERY_STRING"] %></td>
            </tr>
      </table>
</body>
</html>

Откроем браузер и переходим по адресу http://localhost/article.aspx для того, чтобы убедиться, что страница открывается корректно.

Теперь сформируем пару правил для созданного сайта в IIS. Для этого создадим файл web.config в каталоге %SystemDrive%\inetpub\wwwroot\ со следующим содержанием:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
	<rules>
          <rule name="Fail bad requests">
            <match url="." />
            <conditions>
              <add input="{HTTP_HOST}" negate="true" pattern="localhost" />
            </conditions>
            <action type="AbortRequest" />
          </rule>
          <rule name="Rewrite to article.aspx">
            <match url="^article/([0-9]+)/([_0-9a-z-]+)" />
            <action type="Rewrite" url="article.aspx?id={R:1}&title={R:2}" />
          </rule>
        </rules>
	</rewrite>
    </system.webServer>
</configuration>

Если все выполнено верно, то при нажатии на значок URL Rewrite в разделе нашего сайта мы увидим созданные правила.

Созданные нами правила достаточно несложные и реализуют простой функционал.

  • Правило Fail bad requests — прерывает http соединения если host заголовок запроса не совпадает с localhost.
  • Правило Rewrite to article.aspx перезаписывает URL от формата http://localhost/article/234/some-title
    к формату http://localhost/article.aspx?id=234&title=some-title.

Давайте убедимся, что правила действительно работают. Для этого вновь откроем веб-браузер и перейдем по адресу — http://localhost/article/234/some-title.

Тестовая страница для модуля URL Rewrite сообщает нам информацию об оригинальном URL, а также его модификации после применения правила Rewrite to article.aspx.

Если мы попытаемся перейти по адресу http://127.0.0.1/article/234/some-title, то такой запрос будет прерван после применения правила Fail bad requests.

Как диагностировать URL Rewrite?

Наконец мы подошли к главной теме статьи — как диагностировать проблемы или получать журнал ошибок при конфигурации URL Rewrite? Для этого потребуется включить функционал Failed Request Tracing, а также создать правило, в котором мы укажем, что конкретно мы хотим фиксировать.

Конфигурация Failed Request Tracing

В диспетчере IIS, в нужном сайте переходим в раздел Failed Request Tracing.

Включаем трассировку неудачных запросов.

Теперь переходим в раздел конфигурации трассировки неудачных запросов.

Добавляем новое правило трассировки.

Выбираем весь контент для трассировки.

Указываем какие коды ответа необходимо фиксировать. В реальной жизни стоит указывать только те коды, которые вам возвращаются и которые необходимо диагностировать. В нашей статье мы укажем диапазон от 200 до 999.

Выберем поставщика информации для трассировки. В нашем случае это модуль URL Rewrite.

В итоге появиться созданное нами правило трассировки неудачных запросов.

На этом мы закончили конфигурацию трассировки. Теперь, после выполнения хотя бы одного запроса со стороны клиента, в каталоге %systemdrive%\inetpub\logs\FailedReqLogFiles будет сформирован новый журнал, содержащий подробности хода выполнения запроса.

Диагностика правил URL Rewrite

Еще раз перейдем по адресу — http://localhost/article/234/some-title и перейдем в каталог %systemdrive%\inetpub\logs\FailedReqLogFiles\W3SVC1. В этой папке мы увидим файл freb.xsl — таблица стилей, а также fr000001.xml — лог подключения.

Имейте ввиду, что для каждого подключения будет создан отдельный лог. В наших тестовых условиях мы указали, что готовы журналировать соединения с любыми кодами ответа (от 200 до 999) для наглядности. Не стоит так делать на настоящих серверах.

Давайте откроем файл лога при помощи Internet Explorer и перейдем в режим компактного просмотра.

В этом логе нас интересует информация с 35 по 46 строки. Именно на этих событиях модуль URL Rewrite производил обработку подключения. Давайте подробнее остановимся сначала на строках 35-41 и разберем механизм работы первого правила, а потом на строках 42-46 и разберем механизм работы второго правила.

Диагностика первого правила

Напоминаю, что первое правило прерывает запрос, если имя запрашиваемого хоста отличается от localhost (35-41 строчки).

URL_REWRITE_START — Событие сообщает о старте работы URL Rewrite. Свойства события предоставляют следующую информацию:

  • Request URL — запрашиваемый URL — «/article/234/some-title».
  • Scope=»Distributed» сообщает о том, что правило было определено на уровне сайта, а не глобально, на уровне сервера.
  • Type=»Inbound» — тип соединения — входящий.

RULE_EVALUATION_START — Событие сообщает о запуске механизма URL Rewrite для первого правила. Свойства события предоставляют следующую информацию:

  • Rulename — имя правила.
  • Request URL — запрашиваемый URL — «/article/234/some-title».
  • PatternSyntax=»Regex» — для формирования шаблона правила используются регулярные выражения.
  • StopProcessing=»false» — Последующие правила также будут применены, обработка не завершится на текущем правиле.
  • RelativePath=»/» — правило определено на уровне сайта.

PATTERN_MATCH — Событие предоставляет информацию о том, как URL был сопоставлен с шаблоном правила. Свойства события предоставляют следующую информацию:

  • Pattern=».» — шаблон правила. Под знаком точки понимается любой символ.
  • Input=»article/234/some-title» — строка, которая проверяется шаблоном правила.
  • Negate=»false» — в шаблоне не используется отрицание.
  • Matched=»true» — входящий URL подходит под шаблон правила.

CONDITIONS_EVALUATION_START — Событие запускается, если входящий URL совпал с шаблоном правила. Свойства события предоставляют следующую информацию:

  • LogicalGroupping=»MatchAll» — Режим группировки MatchAll подразумевает совпадение всех существующих условий правила.

CONDITION_EVALUATION — Событие предоставляет следующую информацию:

  • Input=»{HTTP_HOST}» — входящая переменная имени хоста для подключения.
  • ExpandedInput=»localhost» — понятное для человека имя хоста для подключения.
  • MatchType=»Pattern» — тип определения соответствия. В нашем случае — шаблон.
  • Pattern=»localhost» — шаблон для соответствия.
  • Negate=»true» — в условии используется отрицание.
  • Succeeded=»false» — итог выполнения условия. В нашем случае входящая строка не совпала с шаблоном.

CONDITIONS_EVALUATION_END — Событие сообщает о том, что условие не выполнено.

RULE_EVALUATION_END — Событие сообщает о том, что правило не выполнено.

Диагностика второго правила

Напоминаю, что второе правило перезаписывает URL, делая его более понятным и удобным для человека (42-46 строчки).

Чтобы не пролистывать статью наверх в поисках лога, дублирую изображение ниже.

RULE_EVALUATION_START — Событие сообщает о запуске механизма URL Rewrite для второго правила. Свойства события предоставляют следующую информацию:

  • Rulename — имя правила.
  • Request URL — запрашиваемый URL — «/article/234/some-title».
  • PatternSyntax=»Regex» — для формирования шаблона правила используются регулярные выражения.
  • StopProcessing=»false» — Последующие правила также будут применены, обработка не завершится на текущем правиле.
  • RelativePath=»/» — правило определено на уровне сайта.

PATTERN_MATCH — Событие предоставляет информацию о том, как URL был сопоставлен с шаблоном правила. Свойства события предоставляют следующую информацию:

  • Pattern=»^article/([0-9]+)/([_0-9a-z-]+)» — шаблон правила. Под регулярным выражением понимается строка, состоящая из трех групп разделяемых прямым слешем. Первая часть начинается с article. Вторая имеет одну или несколько цифр от нуля до девяти. Третья часть содержит одну или несколько цифр от нуля до девяти, либо буквы от a до z.
  • Input=»article/234/some-title» — строка, которая проверяется шаблоном правила.
  • Negate=»false» — в шаблоне не используется отрицание.
  • Matched=»true» — входящий URL подходит под шаблон правила.

REWRITE_ACTION — Событие сообщает о перезаписи URL. Свойства события предоставляют следующую информацию:

  • Substitution=»article.aspx?id={R:1}&title={R:2}» — шаблон перезаписи URL, в соответствии с которым будут производиться изменения. Конструкции R:1 и R:2 обозначают номера групп в шаблоне правила.
  • RewriteURL=»/article.aspx?id=234&title=some-title» — итоговый URL после применения правил перезаписи.

RULE_EVALUATION_END — Событие сообщает о том, что правило выполнено.

URL_REWRITE_END — Событие сообщает о завершении работы модуля URL Rewrite.

Диагностика запрещающего правила

Теперь давайте попробуем смоделировать ситуацию, где пользователь вводит URL, где хост будет отличаться от localhost.

Вновь открываем браузер и вводим в адресной строке — http://127.0.0.1/article/234/some-title. Браузер ответит, что страница не может быть открыта.

Мы уже пробовали выполнять это действие ранее, но тогда мы еще не настроили трассировку неудачных запросов.

Перейдем в каталог %systemdrive%\inetpub\logs\FailedReqLogFiles\W3SVC1 и откроем файл fr000002.xml.

В этот раз нас интересуют строки 35-44. Именно в них зафиксированы события URL Rewrite.

Ключевым моментом для понимания является строка 42. В ней мы можем увидеть, что правило Fail bad requests было применено. В строке 39 описана логика принятия решения правилом.

Полученный адрес 127.0.0.1 не подошел к шаблону условия — localhost. Именно поэтому мы не смогли подключиться, соединение было прервано.

Итоги

Коллеги, в этой статье нам удалось развернуть тестовый стенд и наглядно, по шагам, посмотреть на то, как работает URL Rewrite. Мы получили базовое понимание работы логики и алгоритма принятия решений этого модуля. Теперь вопросы связанные с диагностикой URL Rewrite станут немного легче. Мы разбирали достаточно простые правила, в реальных задачах логи могут быть гораздо больше и сложнее. Напоминаю, что эта статья является переводом с авторскими дополнениями. Официальная документация доступна — здесь.

3 комментария к “Диагностика (troubleshooting) правил модуля URL Rewrite в IIS.

  1. Вы можете помочь с настройкой правила?

    1. Александр, приветствую. Давайте попробуем разобраться 🙂
      Предлагаю перейти в почту.

  2. Александр, если напрямую с сервера с IIS доступен (через VPN Client) некий ресурс, могу ли я я его сделать доступным с других компьютеров в локальной сети через этот сервер? Через перенаправление работать не будет — так как на других ПК нет доступа к этому ресурсу. Перенаправление может помочь? Настроил — но не получается получить доступ.

Обсуждение закрыто.