Вопрос или проблема
У меня есть сервер Apache (версии 2.4.62-1~deb12u2 из Debian 12 «Bookworm», в настоящее время стабильная версия Debian), который обслуживает сайт http://www.example.tld/
с активированной UserDir
, так что http://www.example.tld/~myname/
загружает материалы из /home/myname/public_html/
— пока все в порядке.
Теперь по какой-то причине, либо из-за опечатки, либо из-за неправильно обработанной относительной ссылки или еще чего-то, ссылки с несколькими слешами, вида http://www.example.tld/~myname//somestuff
, начали существовать в сети. Google не любит это, потому что считает их дубликатами. Поэтому я хотел бы перенаправить любой такой URL на канонический http://www.example.tld/~myname/somestuff
. Я использую RedirectMatch
, потому что хотел бы избежать сложности mod_rewrite. Так что, естественно, я попробовал следующее:
RedirectMatch permanent ^/~myname//+(.*)$ /~myname/$1
но это не дает эффекта (независимо от того, помещаю я это до или после директивы, включающей UserDir
): это как будто директивы и не было. Подумая, что может быть я редактирую неправильный файл или использую неправильный синтаксис regexp, я проверил:
RedirectMatch permanent ^/test//+(.*)$ /~myname/$1 # Работает отлично!
и это действительно перенаправляет http://www.example.tld/test//somestuff
на http://www.example.tld/~myname/somestuff
, устраняя двойной слеш (в то время как http://www.example.tld/test/somestuff
вообще не совпадает и возвращает 404, как и ожидалось) — так что нет сомнений, что файл читается, и мои перенаправления в общем работают. Затем я подумал, может быть, нельзя перенаправлять на userdir вообще, но!
RedirectMatch permanent ^/~test/+(.*)$ /~myname/$1 # Работает отлично!
Этот вариант работает отлично и действительно удаляет несколько слешей, как и должно: http://www.example.tld/~test//somestuff
переходит на http://www.example.tld/~myname/somestuff
как и требовалось. И это не проблема с существованием ~myname
, потому что:
RedirectMatch permanent ^/~test//+(.*)$ /~myname/$1 # Без эффекта!
казалось бы, полностью игнорируется (http://www.example.tld/~test//somestuff
возвращает 404, а не перенаправляется, как это было в предыдущем тесте).
В этот момент я думаю, что схожу с ума. Обратите внимание, что я также пробовал перенаправление изнутри файла .htaccess
в /home/myname/
без какого-либо успеха.
Теперь, прежде чем я назову это ошибкой Apache, что я хотел бы спросить:
-
Есть ли что-то явно неправильное в том, что я пытаюсь сделать? Зафиксировано ли такое поведение?
-
Может кто-то другой воспроизвести вышеуказанный странный эффект? Моя конфигурация Apache немного сложна (например, я также использую mod_jk — не в том же месте, но вы никогда не узнаете, какие странные взаимодействия могут быть), и я не могу легко создать минимальный рабочий пример. Также мне сложно попробовать разные версии Apache, так что если кто-то сможет подтвердить странность на новых версиях или сказать, что это исчезло, я буду признателен.
-
Может ли быть, что я пропустил другой способ обойти это и все равно получить
http://www.example.tld/~myname/somestuff
, чтобы перенаправить наhttp://www.example.tld/~myname/somestuff
другим способом? Есть ли такая же проблема у mod_rewrite? -
Стоит ли мне сообщить об этом как об ошибке? Какие другие тесты мне следует провести заранее?
Ответ или решение
К вопросу о странном взаимодействии между директивами UserDir
и RedirectMatch
в Apache, особенно в контексте обработки URL с двойными слэшами, следует подходить комплексно. Это поможет понять, почему ваши попытки перенаправления не работают так, как ожидается.
1. Проблемная ситуация
У вас есть веб-сервер Apache, на котором включен UserDir
, что позволяет пользователям получать доступ к своим собственным директориям через URL, подобные http://www.example.tld/~myname/
. Однако возникает необходимость в редиректе URL с двойными слэшами, такого как http://www.example.tld/~myname//somestuff
, на канонический вид http://www.example.tld/~myname/somestuff
.
2. Почему RedirectMatch
может не работать?
Ваша проблема, когда RedirectMatch
не срабатывает на запросы к UserDir
, может быть связана с тем, как Apache обрабатывает различные директивы, назначенные для пользовательских директорий.
Пункты проверки:
- Порядок директив: Убедитесь, что директива
RedirectMatch
размещена до включенияUserDir
, чтобы она могла обработать запросы до того, как Apache передаст их в модульUserDir
. - Использование
/
внутри регулярных выражений: Регулярное выражение, которое вы используете, должно соответствовать синтаксису Apache, но может оказаться излишне строгим в отношении структуры URL с двойными слэшами.
3. Альтернативные подходы
- Использование
mod_rewrite
: Несмотря на ваши намерения избегатьmod_rewrite
, это может быть более гибкий и мощный инструмент для ваших нужд. Пример правила перенаправления с использованиемmod_rewrite
:RewriteEngine On RewriteCond %{THE_REQUEST} \s/~myname//+(.*) [NC] RewriteRule ^/~myname//+(.*)$ /~myname/$1 [R=301,L]
4. Испытания иdebugging
- Логи Apache: Включите детальное логирование ошибок и запросов. Это может дать понимание того, что именно происходит, когда вы запрашиваете URL с двойными слэшами.
- Тестирование других версий Apache: Возможно, поведение действительно связано с версии Apache. Попробуйте протестировать на более свежих версиях, если это возможно.
5. О возможности сообщения об ошибке
Если описанные вами эксперименты и тесты не решают проблему, возможно, стоит рассмотреть вопрос о сообщении об ошибке. Перед этим выполните следующие шаги:
- Проверьте другие модули и конфигурации, которые могут конфликтовать.
- Соберите дополнительные данные (журналы, конфигурации) для более полного понимания.
Заключение
Ваши наблюдения о несоответствии работы RedirectMatch
и UserDir
могут быть обоснованными. Перепроверьте порядок применения правил, рассмотрите возможность использования mod_rewrite
, а также тщательно изучите логи для выявления дополнительных подсказок. Если после всех ваших усилий проблема останется, целесообразно будет сообщить об этом в соответствующих ресурсах поддержки Apache.