Вопрос или проблема
У меня такая структура папок:
/fonts
/myfont.eot
/myfont.svg
/myfont.ttf
/myfont.woff
/myfont.woff2
/content
/page1
/files
/logo.png
/style.css
/index.html
/page2
/files
/logo.png
/style.css
/index.html
/page3
/files
/logo.png
/style.css
/a
/index.html
/b
/index.html
...
Таким образом выглядят URL, которые нужно вызвать:
example.com/content/page1
example.com/content/page2
example.com/content/page3/a
example.com/content/page3/b
Теперь всё, что я хочу достичь с помощью файла .htaccess
, расположенного в /page3
, это чтобы любой, кто посетит example.com/content/page3
, был правильно перенаправлен на example.com/content/page3/a
(или example.com/content/page3/a/index.html
, мне всё равно, будет ли имя файла в URL или нет).
Я пробовал
DirectoryIndex /content/page3/a/index.html
но в этом случае, когда я открываю example.com/content/page3
, все относительные ссылки в файле /a/index.html
нарушаются из-за отсутствия уровня директории в URL. Кроме того, хотя вызов example.com/content/page3/a
работает, example.com/content/page3/b
выдает 403 Forbidden.
Я пробовал
Redirect 301 /content/page3 /content/page3/a
но это, очевидно, приводит к бесконечной спирали перенаправления на example.com/content/page3/a/a/a/a/a/a/......
, пока сервер не прекратит попытки.
Поэтому я понял, что мне нужна некоторая конфигурация RedirectCond
и RedirectRule
. К сожалению, я не понимаю синтаксис, и все примеры, которые я смотрел, делали это на верхнем уровне с более сложными задачами, такими как перенаправление файлов и подпапок, иногда на другой домен и т.д.
Я пробовал это
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$
RewriteCond %{REQUEST_URI} ^/content/page3/$
RewriteRule ^/content/page3/?$ /content/page3/a [L]
потому что я думал, что это заменит “/content/page3” на “/content/page3/a”, но безрезультатно, это ничего не делает.
Сейчас я пошел по пути использования
DirectoryIndex /content/page3/a/index.html index.html
и заменил относительные ссылки в документе на абсолютные. Это сработало.
Но во-первых, я всё еще предпочёл бы, чтобы ссылки оставались относительными, чтобы документ не сломался в случае, если папку page3
когда-либо переименуют, а во-вторых, я бы предпочёл, чтобы подпапка /a
была в URL для ясности того, что отображается.
Как я могу этого добиться?
Я бы всё еще предпочёл, чтобы ссылки оставались относительными
В этом случае вам действительно нужно внешнее перенаправление, а не внутреннее переписывание или внутренний подс запрос (что вы, по сути, делаете с директивой DirectoryIndex
). И если вы “предпочли бы, чтобы подпапка /a
была в URL”, то вам определенно нужно внешнее перенаправление.
Таким образом выглядят URL, которые нужно вызвать:
example.com/content/page1
example.com/content/page2
example.com/content/page3/a
example.com/content/page3/b
Обращаю внимание, что вы не добавили завершающие слеши в любой из этих URL, которые отображают физические директории. Эти URL должны содержать завершающие слеши для того, что вы пытаетесь сделать, т.е. ссылаться на example.com/content/page1/
, а не example.com/content/page1
. Причина в том, что Apache (mod_dir) в противном случае “исправит” URL с помощью перенаправления 301, чтобы добавить завершающий слеш. Если вы хотите исключить завершающий слеш в этих “директорных” URL, вам нужно будет проделать больше работы.
файл
.htaccess
, расположенный в/page3
Используя mod_rewrite, вы можете сделать следующее:
RewriteEngine On
RewriteRule ^$ /content/page3/a/ [R,L]
Это временное (302) перенаправление. ^$
соответствует пустому пути URL. Он “пустой”, потому что он относителен к текущей директории. mod_dir затем выдаст подс запрос для DirectoryIndex
, т.е. index.html
.
В качестве альтернативы используйте mod_alias RedirectMatch
:
RedirectMatch 302 ^/content/page3/?$ /content/page3/a/
RewriteRule ^/content/page3/?$ /content/page3/a [L]
Это никогда не будет работать, потому что в контексте директории (т.е. .htaccess
) путь URL, который соответствует RewriteRule
шаблону, не начинается со слеша.
Если бы вы написали это в корневом файле .htaccess
, он должен выглядеть так:
RewriteEngine On
RewriteRule ^content/page3/?$ /content/page3/a/ [R,L]
Предыдущие два условия не требуются – если у вас нет нескольких доменов?
Соответствующая директива mod_alias будет такой же, как выше (независимо от того, где расположен файл .htaccess
).
Директива DirectoryIndex
должна быть просто установлена на:
DirectoryIndex index.html
Чтобы обслуживать документ index.html
из запрашиваемой директории.
Redirect 301 /content/page3 /content/page3/a
Это создаст петлю перенаправления, потому что директива mod_alias Redirect
является префиксной и всё, что после совпадения, добавляется к целевому URL, т.е. перенаправленный URL /content/page3/a
совпадает с исходным URL /content/page3
, и /a
добавляется в конец целевого (/content/page3/a
), чтобы стать /content/page3/a/a
и т.д.
Обратите внимание, что 301 (постоянные) перенаправления кэшируются браузером. Вам нужно будет очистить кэш браузера. Всегда проверяйте с 302 (временными) перенаправлениями и только изменяйте на 301 (постоянные) – если это намерение – после того, как вы подтвердите, что всё работает нормально.
Ответ или решение
Чтобы настроить переадресацию с одного подпапки на другую с использованием файла .htaccess
, важно правильно использовать возможности модуля mod_rewrite
или mod_alias
в Apache. В данном случае нам нужно перенаправить запросы с example.com/content/page3
на example.com/content/page3/a
, избегая зацикливания и сохраняя работоспособность относительных ссылок в HTML-страницах.
Структура каталога:
На основании вашей структуры каталогов:
/fonts
/myfont.eot
/myfont.svg
/myfont.ttf
/myfont.woff
/myfont.woff2
/content
/page1
/files
/logo.png
/style.css
/index.html
/page2
/files
/logo.png
/style.css
/index.html
/page3
/files
/logo.png
/style.css
/a
/index.html
/b
/index.html
Решение с использованием .htaccess
-
Создание файла
.htaccess
в каталоге/content/page3
:Вы можете использовать следующую конфигурацию с правилами
mod_rewrite
. Откройте или создайте файл.htaccess
в каталоге/content/page3
и добавьте следующий код:RewriteEngine On RewriteBase /content/page3/ RewriteRule ^$ a/ [R=302,L]
В этом примере:
RewriteEngine On
включает модуль переопределения.RewriteBase
устанавливает базовый путь для правил.RewriteRule ^$ a/ [R=302,L]
говорит серверу переадресовать запрос по умолчанию (когда путь пуст) на/content/page3/a/
с кодом переадресации 302 (временная).
-
Использование
RedirectMatch
:В качестве альтернативы вы также можете использовать директиву
RedirectMatch
:RedirectMatch 302 ^/content/page3/?$ /content/page3/a/
Это правило будет работать аналогично, переадресовывая все запросы к
/content/page3
на/content/page3/a/
, и любой доступ к/content/page3/a
будет корректно обрабатываться, не приводя к путанице.
Примечания:
-
Проверка запросов: Убедитесь, что после внесения изменений вы проверяете запросы с помощью временного редиректа (302). Постоянные переадресации (301) кэшируются браузерами, поэтому они могут вызвать проблемы при тестировании.
-
Относительные ссылки: Если вы хотите сохранить относительные ссылки в вашем
index.html
файле внутри каталогаa
, то данный метод будет идеальным, так как он позволяет сохранять и использовать их, не нарушая структуры каталогов. -
Завершение с косой чертой: Важно убедиться, что вы добавляете или убираете завершающую косую черту при необходимости, чтобы избежать дополнительных редиректов или ошибок 403, так как Apache может интерпретировать URLs по-разному.
Следуя этому руководству, вы сможете настроить переадресацию правильно, обеспечивая тем самым удобство использования и корректное обслуживание ваших страниц.