Проблемы с mod_rewrite, поддоменом и codeigniter

У меня есть установка codeigniter на example.com/ci. У меня есть поддомен foo.example.com. Корневой каталог документа для поддомена foo установлен как home / public_html / ci.

Я использую следующее правило в .htaccess для отправки запросов для foo.example.com на example.com/ci/city/foo.

 RewriteCond %{HTTP_HOST} !^(www)\. [NC]
 RewriteCond %{HTTP_HOST} ^(.*)\.example\.com [NC]
 RewriteRule (.*) http://example.com/ci/city/%1/$1 [L]

Все работает так, как я хочу, за исключением того, что URL-адрес адресной строки меняется с foo.example.com на example.com/ci/city/foo. Я бы хотел, чтобы он остался foo.example.com. В RewriteRule нет R = 301 (раньше было, но я его удалил). Файл .htaccess находится в папке ci /, и это правило касается прежде всего кода codeigniter.

Перенаправление работает отлично, и URL-адрес остается foo.example.com с (ответ Джона Лин)

RewriteCond %{HTTP_HOST} !^(www)\. [NC]
 RewriteCond %{HTTP_HOST} ^(.*)\.example\.com [NC]
 RewriteCond %{REQUEST_URI} !/city/
 RewriteRule (.*) /city/%1/$1 [L]

но контроллер по умолчанию codeigniter вызывается вместо метода foo в городском контроллере.

Любая помощь приветствуется.


person smrkem    schedule 12.04.2013    source источник


Ответы (4)


Когда цель вашего правила перезаписи содержит http://example.com, перенаправление 302 неявно, независимо от того, используется ли флаг R или нет. Вам необходимо указать путь URI на основе корня документа поддомена, поэтому я предполагаю, что вам нужно что-то вроде:

RewriteCond %{HTTP_HOST} !^(www)\. [NC]
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com [NC]
RewriteCond %{REQUEST_URI} !/city/
RewriteRule (.*) /city/%1/$1 [L]

Если корень документа поддомена находится в каталоге /ci/.

Другой вариант - использовать флаг P для обратного прокси запроса:

RewriteCond %{HTTP_HOST} !^(www)\. [NC]
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com [NC]
RewriteRule (.*) http://example.com/ci/city/%1/$1 [L,P]
person Jon Lin    schedule 12.04.2013
comment
Благодарю за ваш ответ. При попытке первого решения я получаю ошибку сервера 500. Корнем документа моего поддомена является каталог / ci. Второе решение приводит к неверному запросу. Ваш браузер отправил запрос, который этот сервер не смог понять. Размер поля заголовка запроса превышает ограничение сервера. X-Forwarded-Host / n - person smrkem; 12.04.2013
comment
@smrkem внес правку, чтобы предотвратить зацикливание первого цикла. - person Jon Lin; 12.04.2013
comment
Ваше исправление избавило от ошибки сервера, спасибо, но оно просто перейдет к контроллеру по умолчанию внутри codeigniter. Вот что происходит, когда правила перезаписи отсутствуют. Я намерен вызвать городской контроллер и функцию foo в нем. - person smrkem; 12.04.2013

Ваш опыт может варьироваться в зависимости от этого (возможно, потребуется доработать его, чтобы он соответствовал вашему серверу и условиям), но, проведя некоторое тестирование на моем Mac, вот что у меня было умеренным успехом:

Структура каталогов

public_html/
  ci/
    application/
    system/
    .htaccess
    index.php

Я предполагаю, что у вас в корневом public_html каталоге есть другие вещи. Поэтому я позволяю .htaccess сосредоточиться на материалах, связанных с CodeIgniter, оставив его в ci директории.

.htaccess

DirectoryIndex index.php

RewriteEngine on

RewriteCond %{HTTP_HOST} ^(.*)\.ciwildsub\.dev [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php/city/%1/$1 [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]

Это довольно понятно, но первый блок - это проверка вашего поддомена. Я не стал исключать www, но вы можете захотеть (как я уже сказал, ваш пробег может отличаться). Второй блок - это стандартное удаление CodeIgniter index.php.

Эти правила будут применяться только к sub.example.com или example.com/ci/ URL-адресам, поскольку, как я уже сказал, я предполагаю, что в вашем корне есть вещи, которые не должны нарушаться при перезаписи.

Конфигурация CodeIgniter

$config['uri_protocol'] = 'PATH_INFO';

Из-за того, как Apache обрабатывает URL-адрес типа example.com/index.php/controller/method, он обходит index.php и обрабатывает его, как любой другой сегмент каталога. Кроме того, mod_rewrite не обязательно останавливать на теге [L] - он останавливает обработку .htaccess в этой точке, проходит через RewriteRule, а затем пропускает этот URL через .htaccess. Установка PATH_INFO помогает убедиться, что CodeIgniter правильно извлекает текущий URI, и наш .htaccess не застревает в цикле проверки.

Однако я отмечу, что я не совсем доволен тем, что вижу в моем выводе RewriteLog - там должен быть способ дальнейшей оптимизации, я просто еще не уверен в этом (На сегодня я закончил с этим возиться!). Извините, если какое-либо объяснение здесь немного не в порядке - я не администратор сервера или эксперт по mod_rewrite, мне просто было весело возиться с этим. Если мне удастся найти лучшее решение, я обязательно обновлю это.


Похоже, END flag идеально подходит для таких ситуаций ( для предотвращения [L] циклов), но это доступно только в Apache 2.3.9+. Поиск продолжается.

person Aken Roberts    schedule 12.04.2013
comment
Спасибо за ваш ответ. Ваши правила выдают мне ошибку 500 на сервере, которую я не могу диагностировать, так как у меня нет доступа к RewriteLog. Однако ваша конфигурация codeigniter была второй половиной моего решения. Мне пришлось изменить его с PATH_INFO на ORIG_PATH_INFO, но теперь он обращается к нужному контроллеру. Спасибо. - person smrkem; 12.04.2013
comment
Да, настройки могут так сильно различаться, что трудно дать вам точный ответ, не имея точного дубликата. Однако рад, что вам удалось заставить все работать. - person Aken Roberts; 13.04.2013

Я заставил его работать правильно, используя следующее правило перезаписи

   RewriteCond %{HTTP_HOST} !^(www)\. [NC]
 RewriteCond %{HTTP_HOST} ^(.*)\.example\.com [NC]
 RewriteCond %{REQUEST_URI} !/city/
 RewriteRule (.*) /city/%1/$1 [L]

и установив

$config['uri_protocol'] = 'ORIG_PATH_INFO';

в файле конфигурации codeigniter. Спасибо за помощь.

person smrkem    schedule 12.04.2013

Это сработало для меня

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /file_path/to/subdomain
    RewriteCond $1 !^(index\.php|images|robots\.txt)
    RewriteRule ^(.*)$ /index.php/$1 [L]
    RewriteCond %{REQUEST_URI} ^application.*
        RewriteRule ^(.*)$ /index.php?/$1 [L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)$ index.php?/$1 [L]
    </IfModule>

    <IfModule !mod_rewrite.c>
        ErrorDocument 404 /index.php
    </IfModule> 
person aphoe    schedule 04.06.2014