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

RewriteRule для root без флага R не работает

Пытаюсь сделать систему кеширования с файлами. И я думал об использовании перезаписи мода для обслуживания кешированного файла, если он существует, или файла php (который создаст статический кеш html), если нет.

Вот первый образец, который я придумал

         <IfModule mod_rewrite.c>
            RewriteEngine On

            RewriteRule ^$ /cache/home.html [L,NC]
            RewriteCond %{REQUEST_URI} /cache/
            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteRule ^cache/home.html /index.php [L]

            RewriteRule ^page/([0-9]*) /cache/page_$1.html [L,NC]
            RewriteCond %{REQUEST_URI} /cache/
            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteRule ^cache/page_([0-9]*).html /page.php?&id=$1 [L]
        </IfModule>

Это правильно работает для внутренних страниц. Если я позвоню http://www.example.site/page/1 или http://www.example.site/page/2 он правильно обслуживает кешированный файл или страницу php в зависимости от того, существует файл или нет.

Проблема в том, что он не работает для основного сайта http://www.example.site

Если я добавлю флаг перенаправления для дома, он действительно работает правильно

RewriteRule ^$ /cache/home.html [L,NC,R]

Но, очевидно, в этом случае, если я позвоню на основной сайт и мне подадут http://www.example.site/cache/home.html это не то, что я искал.

Вот пара строк журнала, в которых может быть проблема:

[Wed Aug 05 11:59:11.751277 2015] [rewrite:trace1] [pid 30670] mod_rewrite.c(468): [client 10.1.1.1:53595] 10.1.1.1 - - [m.site.com/sid#7f7850ecb038][rid#7f7850e480a0/initial] [perdir /home/www/site.com/public/mobile/] internal redirect with /cache/home.html [INTERNAL REDIRECT]
[Wed Aug 05 11:59:11.751339 2015] [rewrite:trace3] [pid 30670] mod_rewrite.c(468): [client 10.1.1.1:53595] 10.1.1.1 - - [m.site.com/sid#7f7850ecb038][rid#7f7850e420a0/subreq] [perdir /home/www/site.com/public/mobile/] strip per-dir prefix: /home/www/site.com/public/mobile/index.html -> index.html

Пока с флагом R

[Wed Aug 05 12:04:34.333591 2015] [rewrite:trace1] [pid 31746] mod_rewrite.c(468): [client 10.1.1.1:53613] 10.1.1.1 - - [m.site.com/sid#7f7850ec1038][rid#7f7850e440a0/initial] [perdir /home/www/site.com/public/mobile/] redirect to http://m.cmstest.site.com/cache/home.html [REDIRECT/302]
[Wed Aug 05 12:04:34.343609 2015] [rewrite:trace3] [pid 31746] mod_rewrite.c(468): [client 10.1.1.1:53613] 10.1.1.1 - - [m.site.com/sid#7f7850ec1038][rid#7f7850e420a0/initial] [perdir /home/www/site.com/public/mobile/] strip per-dir prefix: /home/www/site.com/public/mobile/cache/home.html -> cache/home.html

Кажется, что первый, без флага R, после правильного ВНУТРЕННЕГО ПЕРЕНАПРАВЛЕНИЯ в cache / home.html он переходит к поиску index.html (которого на самом деле не существует)

Ваше первое правило гласит:

RewriteRule ^$ /cache/home.html [L,NC]

В L flag сообщает mod_rewrite о прекращении обработки на этом этапе, и это проблема, о которой вы спрашиваете. Обходной путь 'R' означает, что новое правило переписывается, как ожидалось, по второму запросу, но L предотвращает это по первому. Так же NC flag здесь является избыточным, поскольку не может быть символов пути, на которые влияет чувствительность к регистру.

Хотя это не является частью вашего вопроса, также подумайте над следующим.

RewriteRule ^cache/home.html /index.php [L]

Вы, вероятно, захотите сопоставить с ^cache/page.html$, так что он не принимает cache/home.htmlxyz, практическое влияние, вероятно, будет минимальным. Также есть правило:

RewriteRule ^page/([0-9]*) /cache/page_$1.html [L,NC]

Флаги, вероятно, по-прежнему неуместны. В NC flag на самом деле что-то здесь делает, но я бы сказал, что это нежелательно. Также учтите, что числовая последовательность в вашем регулярном выражении может иметь нулевую длину, что, как я подозреваю, нежелательно, поэтому, возможно, вы хотите ([0-9]+)? Вы, вероятно, также захотите завершить это с помощью '$', поскольку в настоящее время вы будете соответствовать, например, /page/foobar, и вы также не хотите совпадать /page/123foobar. Итак, у вас будет:

RewriteRule ^page/([0-9]+)$ /cache/page_$1.html

РЕДАКТИРОВАТЬ:

См. Комментарии ниже о том, почему соответствие ^$ может не сработать для вас. Кроме того, если это не поможет, попробуйте добавить mod_rewrite:trace3 на ваш LogLevel директиву и определите, где именно что-то пошло не так. Вывод является подробным, но вы многому научитесь, а если вы все еще озадачены, у вас будет больше деталей, которые мы сможем вернуть.

Проблема, похоже, связана с подзапросами, как в этом ответе: https://stackoverflow.com/questions/9618865/mod-rewrite-mysterious-subreq

Как видно из журнала, после первого правильного внутреннего перенаправления второй вызов относится к подзапросу, который пытается найти index.html в корневом каталоге.

Я пробовал добавить опцию -MultiViews как в ответе, который я связал, но это все еще не сработало. Apache все еще блокировал подзапрос в корне веб-сайта.

В итоге я получил небольшое «взломанное» решение, которое проверяет, является ли запрос подзапросом, и в этом случае ищет ли он index.* файл в корне он перенаправит на /cache/home.html

        RewriteCond %{IS_SUBREQ} t
        RewriteCond %{REQUEST_URI} ^(/index.\w+|/)?$
        RewriteRule ^ /cache/home.html [L]

Это отлично работает, в том смысле, что в итоге получается именно то, что я пытался сделать.

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