Как перенаправить из одной подпапки в подпапку подпапки с помощью htaccess

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

У меня такая структура папок:

/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

  1. Создание файла .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 (временная).
  2. Использование 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 по-разному.

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

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

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