Использование Apache mod_rewrite для перенаправления на статический контент, если существует

Фон

Я оптимизирую некоторые страницы с высокой посещаемостью, создавая статический кеш. Поскольку содержимое меняется не часто, механизм генерации и аннулирования кэша был простым. В настоящее время, однако, я обращаюсь к кешу через PHP (основной file_exists() проверять). Я хотел бы довести это до уровня веб-сервера, чтобы полностью исключить PHP.

спекуляция

У меня будут тысячи кэшированных страниц. Итак, дерево каталогов, которое я представляю:

year -> first id of digit -> second id of digit -> id.html

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

Вот пример входящего URL:

/2011/37823/some_slug

Некоторый псевдокод, используя приведенный выше URL:

RewriteCond %{REQUEST_URL} ^(\d{4})/...
RewriteCond /cache/$1/$3/$4/$2.html -f
RewriteRule - /cache/$1/$3/$4/$2.html [L]

Вопросы

  • Как я могу создать RewriteRuleэто для выше?
  • Есть ли лучший способ сделать это (используя технологии стека LAMP)?

2 ответа

Решение

Это потребует настройки, так как ваше регулярное выражение не соответствует шаблону, который вы перечисляете (порядок меняется), но следующее основано на вашем примере URL:

RewriteCond %{DOCUMENT_ROOT}/cache/$1$2$3\.html -f
RewriteRule ^(\d+)(/\d+)(/[^/]+)$ /cache/$1$2$3.html [L]

Если вы хотите немного больше вложенности (папки, основанные на первой и второй цифрах идентификаторов, но игнорируете остальную часть средней части URL), тогда это будет:

RewriteCond %{DOCUMENT_ROOT}/cache/$1$2/$3$4\.html -f
RewriteRule ^(\d+)(/\d)(\d)\d*(/[^/]+)$ /cache/$1$2/$3$4.html [L]

Сначала проверяется RewriteRule, чтобы увидеть, применимо ли это правило. RewriteCond затем проверяет, существует ли файл (DOCUMENT_ROOT является корнем сайта) с использованием снимков с RewriteRule, Если это существует, то условия выполняются и RewriteRule переписывает URL, обслуживая кэшированную страницу перед тем, как прекратить попытки переписать [L],

С точки зрения лучших вариантов, это лучше, чем у PHP, поскольку он не запускает PHP для кэшированных страниц. Однако он будет проверять шаблон для каждого запроса ресурса.

Это, я думаю, должно работать для вас:

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/(\d{4})\/((\d)(\d)\d+)
RewriteCond %{DOCUMENT_ROOT}/cache/%1/%3/%4/%2.html -f
RewriteRule ^.* /cache/%1/%3/%4/%2.html [L,QSA]

Первое условие соответствует /(ГОД)/((цифра1)(цифра2) цифра3-к-n). Парантезы говорят системе хранить значения внутри переменных%1-%4. Пожалуйста, обратите внимание на сложную часть, где есть парантезы внутри парантезов. Кажется, что регулярное выражение подсчитывает порядок от начала / открытия паразита, поэтому внешний ( вокруг идентификатора будет%2, а затем digit1 будет%3 и т. д.

Второе условие проверяет полный путь к файлу. DOCUMENT_ROOT дает вам путь к локальной файловой системе. Обратите внимание, я использую %и не $, Это потому, что я использую сохраненные переменные из предыдущей строки, а не текущей.

RewriteRule просто переписывает все на ваш новый путь. [L] говорит apache, чтобы он прекратил искать больше записей, а [QSA] (Query String Append) возвращает строку запроса после перезаписи (не уверен, что вам это нужно).

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