Попробуйте переписать на другой URL, если это приведет к 404.

Вопрос или проблема

У меня есть локальный сервер Tomcat, который я разрабатываю, используя локальный экземпляр IIS в качестве прокси.

Я делаю это потому, что развертывание сервера — это мучительный процесс, так как много контента не является (как я бы это описал) самодостаточным. Контент из различных проектов в основном копируется в корневую директорию сервера. Я не хотел бы сталкиваться с этой проблемой настройки, поэтому с помощью модуля перезаписи я мог бы в основном переписывать URL на виртуальные директории.

Например,

/js/* -> /someproject/js/*
/css/* -> /someproject/css/*
/**/*.pdf -> /someotherproject/pdf/*

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

Например,

/someproject1/file1.txt -> /file1.txt
/someproject2/book2.doc -> /book2.doc

Таким образом, учитывая URL /file1.txt, я не знал бы, могу ли я переписать его, чтобы перейти к someproject1 или someproject2. Я подумываю, что это может сработать, если будет какой-то порядок тому, к каким URL пытаться переписать. Таким образом, я мог бы взять URL, например, /file3.txt, и переписать его на первый из этих шаблонов, который оказывается действительным.

/someproject1/file3.txt     # если 404, попробуйте следующее
/someproject2/file3.txt     # если 404, попробуйте следующее
/someotherproject/file3.txt # если 404, попробуйте следующее
/file3.txt                  # запасной вариант

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

Мне удалось заставить это работать.

Первой трудностью было то, что я не осознавал, что не все типы условных совпадений доступны в глобальной области (где я и писал свои правила). Доступен был только Pattern. Мне пришлось изменить область на “распределенную” (правила по сайту), чтобы получить доступ к типам совпадения IsFile и IsDirectory.

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

<rule name="try in project/content" stopProcessing="false">
    <match url=".*" />
    <action type="Rewrite" url="project/content/{R:0}" />
</rule>
<rule name="verify project/content" stopProcessing="false">
    <match url="(project)/content(/.*)" />
    <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    </conditions>
    <action type="Rewrite" url="{R:1}{R:2}" />
</rule>

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


Таким образом, для моего примера в вопросе я установлю эти правила:

<rule name="try in someproject1" stopProcessing="false">
    <match url=".*" />
    <action type="Rewrite" url="someproject1/{R:0}" />
</rule>
<rule name="try in someproject2 otherwise" stopProcessing="false">
    <match url="someproject1/(.*)" />
    <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    </conditions>
    <action type="Rewrite" url="someproject2/{R:1}" />
</rule>
<rule name="try in someotherproject otherwise" stopProcessing="false">
    <match url="someproject2/(.*)" />
    <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    </conditions>
    <action type="Rewrite" url="someotherproject/{R:1}" />
</rule>
<rule name="fallback to root otherwise" stopProcessing="false">
    <match url="someotherproject/(.*)" />
    <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    </conditions>
    <action type="Rewrite" url="{R:1}" />
</rule>

Ответ или решение

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

Введение в проблему

В ходе разработки на локальном сервере Tomcat с использованием IIS в качестве прокси, вы столкнулись с проблемой многоуровневого перенаправления URL. Существуют случаи, когда определенные файлы находятся в разных проектах, и их невозможно однозначно идентифицировать по названию. Ваша цель – разработать систему, которая сначала попытается найти файл в одном проекте, и только затем продолжит поиск в других.

Стратегия решения

Для реализации данного механизма вы можете воспользоваться правилами переработки URL в IIS, написав последовательность правил, которые будут проверять существование файла и, в случае отсутствия, пытаться перенаправить на следующий путь.

Пример конфигурации правил

Чтобы добиться требуемого результата, вы можете использовать следующие правила переписывания:

<rule name="Пробуем найти в someproject1" stopProcessing="false">
    <match url=".*" />
    <action type="Rewrite" url="someproject1/{R:0}" />
</rule>

<rule name="Пробуем найти в someproject2, если не найдено" stopProcessing="false">
    <match url="someproject1/(.*)" />
    <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    </conditions>
    <action type="Rewrite" url="someproject2/{R:1}" />
</rule>

<rule name="Пробуем найти в someotherproject, если не найдено" stopProcessing="false">
    <match url="someproject2/(.*)" />
    <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    </conditions>
    <action type="Rewrite" url="someotherproject/{R:1}" />
</rule>

<rule name="Резервный вариант: корень проекта" stopProcessing="false">
    <match url="someotherproject/(.*)" />
    <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    </conditions>
    <action type="Rewrite" url="{R:1}" />
</rule>

Пояснение правил

  1. Первое правило: Принимает любой запрос и пытается переписывать его в директорию someproject1.
  2. Второе правило: Если файл не найден в someproject1, происходит попытка поиска в someproject2.
  3. Третье правило: Аналогично, если файл отсутствует в someproject2, проводится проверка в someotherproject.
  4. Четвёртое правило: В качестве последнего шага выполняется попытка обратиться к корневой директории.

Заключение

Данная структура позволяет гибко управлять перенаправлением запросов и свести к минимуму возникновение ошибок 404. Убедитесь, что ваше приложение корректно обрабатывает конфликты в именах файлов, и используйте модуль переписывания IIS, чтобы управлять очередностью проверки доступных ресурсов. Понимание базовых концепций работы с URL и правил переписывания является ключом к успешной реализации данной стратегии.

Эта реализованная схема не только поможет вам избежать потерь в ненужных 404 ошибках, но и повысит общий пользовательский опыт ваших конечных пользователей.

Оцените материал
Добавить комментарий

Капча загружается...