Про секретную админку, поддомены и прочие тонкости маршрутизации в Alto CMS

Довольно часто встречаются такие вопросы:
А как сделать, чтобы админка работала не по адресу site.com/admin, а по секретному адресу, который знаю только я? Или вопрос из этой же серии: как сделать, чтоб блоги открывались не по адресу site.com/blog/blabla, а, например, по адресу site.com/section/blabla?

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

В общих чертах, полагаю, большинство из вас понимает, как работает маршрутизатор (роутер): берет запрашиваемый URL, разбирает его на составляющие и вызывает нужный экшен. При этом обработка URL проходит через несколько наборов правил, которые могут задаваться в конфиг-файле (причем, именно в таком порядке):
  • проверка правил внешнего редиректа
  • правила обработки доменов
  • обработка переопределения запроса («внутренний реврайтинг»)
  • внутренний редирект контроллеров (экшенов)
  • определение класса контроллера (экшена)
Теперь обо всем этом по порядку.

Правила внешнего редиректа
О внешнем редиректе средствами движка, кстати, есть отдельная статья, но раз уж пишем о настройках маршрутизации, то не будет лишним напомнить об этом и здесь.

Вообще-то, эти правила лучше всего задавать в настройках хоста — в конфиге apache или nginx, либо в файле .htaccess. Но если по каким-то причинам вы не можете этого сделать (например, конфигурационные файлы не доступны вам для редактирования или просто боитесь трогать их, дабы не сломать все по неопытности), то вы можете настроить эти правила в конфигурационном файле движка. Обратите внимание, что здесь анализируется полный URL, включая протокол. Например:
$config['router']['redirect'] = array(
    // проверка протокола и редирект с HTTP на HTTPS
    'http://*' => 'https://*',
    // редирект с одно адреса на другой с кодом 302 (по умолчанию используется код 301)
    'http://site.com/perm-path/*.html' => array('http://site.com/temp-path/*.html', 302),
    // задание редиректа с помощью регулярного выражения
    '[~(.+/)blabla/(\d+).html$~]' => '$1$2.html',
);
Как видите, правила для роутера можно задавать либо в простой форме (при этом можно использовать символ «*»), либо в виде регулярного выражения, но тогда нужно его обязательно поместить в квадратные скобки.

Правила обработки доменов
При обработке этих правил анализируется только доменное имя, без протокола и без полного пути. Сразу приведем пример, из которого будет все ясно:
$config['router']['domain'] = array(
    '*.site.com' => 'blog/*',
);
Думаем, особо не надо объяснять, что тут в качестве поддоменов работают блоги. Если нужно в поддомены поставить профили юзеров, то, соответственно:
$config['router']['domain'] = array(
    '*.site.com' => 'profile/*',
);
Но если требуется, то можно и явно задавать правило для конкретного поддомена, например, так:
$config['router']['domain'] = array(
    'wiki.site.com' => 'blog/wiki',
);

Но при работе с поддоменами есть несколько важных деталей:
1) Альто-сайт обязательно должен быть в корне, т.е. именно site.com, но не site.com/alto
2) URL для runtime-файлов должен быть относительным, а URL сайта должен задаваться явно:
$config['path']['root']['url'] = 'https://site.com/';
$config['path']['runtime']['url'] = '/_run/';
3) В шаблонах нужно правильно задавать адреса профилей юзеров и блогов. Т.е. вот так:
<a href="{$oUser->getProfileUrl()}">Ссылка на профиль</a>
<a href="{route page="profile/username"}">Другой вариант ссылки на профиль</a>
<a href="{R::GetPath("profile/username")"}>Третий вариант ссылки на профиль</a>
<a href="{route page="profile"}username">А это НЕВЕРНЫЙ вариант</a>

Аналогично для блогов:
<a href="{$oBlog->getLink()}">Ссылка на блог</a>
<a href="{$oBlog->getUrlFull()}">Синоним предыдущего варианта</a>
<a href="{route page="blog/blogname"}">Другой вариант ссылки на блог</a>
<a href="{R::GetPath("blog/blogname")"}>Еще вариант ссылки на блог</a>
<a href="{route page="blog"}blogname">А это НЕВЕРНЫЙ вариант ссылки</a>
Хоть это и очевидно, но на вмякий случай уточним, что если вы задумали обрабатывать домены/поддомены на уровне движка, то сервер у вас должен быть настроен так, чтобы эти доменны/поддомены были алиасами основного домена.

Правила переопределения запроса или «внутренний реврайтинг»
Обычно этот набор правил используется для довольно тонкого тюннига маршрутизации. И анализируется только путь запроса. Например, для URL site.com/some-action/other-event/foo/bar/ будет анализироваться some-action/other-event/foo/bar/. Например, с помощью такого правила в конфиге по умолчанию отсекается обработка движком несуществующих статических файлов:
$config['router']['uri'] = array(
    // запрет обработки статичных файлов с заданными расширениями
    /* допустимые значения:
     *  - @ignore   - запрос игнорируется и его обработка прекращается
     *  - @die(msg) - обработка запроса прекращается с выдачей сообщения msg
     *  - @404      - обработка прекращается с выдачей кода 404
     */
    '[~.+\.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)\/?$~i]' => '@404',
);

Внутренний редирект контроллеров
Это довольно простой вид правил, который используется чаще всего. Он указывает, с какого контроллера на какой нужно адресовать запрос. Например, мы хотим, чтобы на нашем сайте «блоги» назывались «разделами». И логично, если адрес раздела будет выглядеть не site.com/blog/blabla/, а, скажем, site.com/section/blabla/. Для этого задается очень простая настройка:
$config['router']['rewrite'] = array(
    'section' => 'blog', // все, что запрашивается по адресу /section перенаправляется на обработчик /blog
);
Другой пример: мы хотим, чтобы админка сайта вызывалась не по site.com/admin, а по секретному адресу, о котором никто не знает, например, site.com/secret-admin. Делаем так:
$config['router']['rewrite'] = array(
    'secret-admin' => 'admin',
);

Но ведь эта переадресация не отменяет работу и по стандартному адресу — site.com/admin. Чтобы ее отменить, нужно добавить в конфиг следующее:
$config['router']['uri'] = array(
    'admin/*' => '@404',
);

Эта настройка говорит о том, что все обращения по старому адресу админки должны выдавать ошибку 404.

Определение класса контроллера (экшена)
Ну, и, наконец, последний набор правил, который обрабатывается роутером, если запрос все же прошел через все предыдущие — мы можем для каждого контроллера задать класс, который будет его обрабатывать. Этот набор правил задается в секции router.page конфига нашего сайта. И по умолчанию запрос контроллера 'error' обрабатывается классом ActionError, запрос registration — классом ActionRegistration, и т.д. Но если вы разработчик и пишете расширения для сайта, то вы вполне можете задать собственные обработчики контроллеров.

И, в заключение, напомню еще раз порядок обработки правил:
  • сначала обрабатываются правила внешнего редиректа (и это единственный набор правил, который может направить браузер по другому адресу, все остальные правила работают внутри движка, незаметно для глаз посетителя сайта)
  • затем проверяются правила обработки доменов (можем назначить соответствующий контролер любому домену или поддомену)
  • потом идет «внутренний реврайтинг» — внутри маршрутизатора перенаправляем что угодно куда угодно
  • внутренний редирект контроллеров — самый простой способ внутренней переадресации
  • определение класса контроллера — задаем, какой Action-класс будет непосредственно обрабатывать запрос

Похожие статьи

  • Внешний редирект средствами движка
    В версии 1.1 появилась интересная (а для каких-то случаев и весьма полезная) возможность — внешний редирект. Вообще-то, этот функционал, в какой-то степени, является аналогом механизма rewrite, который активно...
  • Как в плагине разрешить домен
    А именно, как в плагине (т.е. программно) разрешить домен для вставки iframe в публикацию? Конструкция, успешно применяемая ранее и некогда подробно описанная PSNet-ом работать не желает... Спасибо за подсказки и...
  • Загрузка картинок на другой сервер и хитрый редирект
    Приветствую! Ребята, подскажет, как сделать, чтоб изображение загружались на другой сервер? Пример: имеем site.ru, а все картинки лежать и загружаются на другой сервер img.site.ru. Так же интересует, возможно ли...
  • Возможен ли реврайт любого урла из плагина?
    Сабж. Хотел сделать возможность динамического переопределения урлов администратором. Но обращение к каким-либо классам в конфиге невозможно (надо получить список урлов), а в методе Init() плагина что-либо делать с...

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.