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