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

Apache2: 400 неверный запрос с правилами перезаписи, в журнале ошибок ничего нет?

Это сводит меня с ума.

Предыстория: я использую встроенные Apache2 и PHP, которые поставляются с Mac OS X 10.6.

У меня следующая настройка vhost:

NameVirtualHost *:81

<Directory "/Users/neezer/Sites/">
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

<VirtualHost *:81>
    ServerName lobster.dev
    ServerAlias *.lobster.dev
    DocumentRoot /Users/neezer/Sites/lobster/www

    RewriteEngine On
    RewriteCond $1 !^(index\.php|resources|robots\.txt)
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1 [L,QSA]

    LogLevel debug
    ErrorLog /private/var/log/apache2/lobster_error
</VirtualHost>

Это в /private/etc/apache2/users/neezer.conf.

Мой код в lobster project это PHP с Фреймворк CodeIgniter. Пытаюсь загрузить http://lobster.dev:81/ дает мне:

ошибка 400, неверный запрос

Обычно я проверял свои журналы, чтобы узнать, что вызвало это, но мои журналы пусты! Я посмотрел в оба /private/var/log/apache2/error_log и /private/var/log/apache2/lobster_error, и ни один из них не записывает ЛЮБОЕ сообщение, относящееся к 400. У меня LogLevel установлен в debug в /private/etc/apache2/http.conf.

Удаление правил перезаписи избавляет от ошибки, но эти же правила работают на моем хосте MAMP. Я перепроверил и rewrite_module загружается в мою установку Apache по умолчанию. Мой http.conf можно найти здесь: https://gist.github.com/1057091

Что дает? Дайте мне знать, если вам понадобится дополнительная информация.

ПРИМЕЧАНИЕ. Я НЕ хочу добавлять правила перезаписи в .htaccess в каталоге проекта (он зарегистрирован в репозитории git, и я не хочу его трогать).

Для сложных правил mod_rewrite рекомендуется регистрировать последовательность событий, чтобы увидеть, что происходит. Сделайте это, используя RewriteLog, и провернуть RewriteLogLevel чтобы увидеть подробности.

mod_rewrite очень гибкий, и с помощью правил перезаписи можно многое делать, а также он довольно сложен. Постороннему будет трудно отладить ваши правила, не видя более широкого контекста. Лучшее, что вы можете сделать, отладить самостоятельно. Следите за журналами в одном окне, пока вы экспериментируете с изменениями конфигурации во втором окне. Внесите небольшое изменение, сохраните файл, перезагрузите apache и снова нажмите URL-адрес. Повторение.

Вот хорошее описание RewriteLog от Apache руководство:

Переписать журнал

При использовании мощных и сложных функций mod_rewrite почти всегда необходимо использовать RewriteLog для помощи в отладке. Этот файл журнала производит подробный анализ того, как механизм перезаписи преобразует запросы. Уровень детализации контролируется директивой RewriteLogLevel.

Ваша замена в <virtualhost> context использует неабсолютный URL. Вы не можете сделать это вне контекста Directory / htaccess.

Еще несколько примечаний, которые стали слишком большими, чтобы их можно было поместить в простой комментарий:

RewriteCond $1 работает, но довольно опасно и хрупко. В частности, вы могли бы легко переписать RewriteRule, чтобы полностью отключить функциональность этого RewriteCond, и вы бы никогда не узнали об этом. Использование %{REQUEST_URI} рекомендуется как решение, à la RewriteCond %{REQUEST_URI} ^/(index\.php|resources|robots\.txt).

Следующая проблема: эти две строчки:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

не функциональны, как представлено. Их либо нужно разместить внутри <Directory> строфы или модифицированы для использования макросов упреждающего просмотра (например, RewriteCond %{LA-U:REQUEST_FILENAME} !-f).

Фактическая причина, по которой вам нужно удалить / в том, что .htaccess снимает ведущую / из первого аргумента RewriteRule, тогда как он доставляется с / без изменений в RewriteRules в httpd.conf (или его Included), что важно запомнить, если вы когда-нибудь попытаетесь переместить это правило обратно в .htaccess. Вы можете изменить правило, сделав его независимым от .htaccess / httpd.conf, выполнив что-то вроде RewriteRule ^/?(.*)$ index.php/$1 [L,QSA].

И последнее замечание: как вы можете видеть в правиле выше, вам не нужно избегать / с обратной косой чертой.