Обработчик Rails 404 для URL-адресов, отличных от Rails

Я унаследовал сайт с сотнями разбросанных файлов HTML и PHP, не относящихся к фреймворку, которые я переношу на Ruby on Rails 3.0.

По мере добавления функциональности в приложение Rails соответствующие страницы удаляются из корня документа; но, поскольку на них часто есть ссылки в Google или на внешних сайтах, простой возврат 404 недопустим.

Например, URL-адрес типа «/contact.php» должен перенаправлять на «/app/contact/».

Для первых нескольких случаев я создал простые html-файлы-заглушки в старых местах с метатегами внутри для выполнения перенаправления. Это плохо масштабируется, особенно когда я начинаю заменять страницы продуктов, которых тысячи.

Я предпочитаю удалить старые страницы, а затем отправить их обработчику 404 в новое приложение Rails, которое проверит URL-адрес с помощью регулярных выражений и поиска в базе данных, чтобы попытаться выяснить, что представляет собой замещающая страница, а затем выполнит перенаправление 301 на это. новая страница.

В httpd.conf я разместил директиву:

ErrorDocument 404 /app/error/handle404
# /app/error is a rails url.

Когда я нажимаю «http://localhost/does-not-exist», это вызывает вызов моего ErrorController, как и ожидалось.

Однако внутри контроллера я не могу найти исходный путь («/не существует») в запросах, request.headers или ENV — я вызывал вероятные методы, такие как request.request_uri (который содержит /app/ error/handle404) и изучение request.headers и ENV без нахождения ожидаемого исходного пути.

Apache access_log показывает только запрос /does-not-exist, указывая на то, что он прозрачно вызвал /app/error/handle404 (без перенаправления или создания второго запроса).

Как я могу получить доступ к исходному URL?

Изменить: чтобы уточнить, вот последовательность событий:

  1. Пользователь переходит по устаревшему пути, например http://mysite/foo.php, возможно, по какой-то древней ссылке из блога.
  2. ... но foo.php больше не существует!
  3. это 404, поэтому Apache вызывает ErrorDocument
  4. директива "ErrorDocument 404 /railsapp/error/handle404"
  5. Rails направляет это в действие ErrorController "handle404" - это работает правильно
  6. проблема: в ErrorController, request.request.uri, request.headers не дают никаких сведений о том, какой URL-адрес на самом деле пытался получить пользователь, например "/foo.php"; Мне нужно знать исходный URL-адрес, чтобы обслуживать соответствующую страницу замены.

person Matt Hucke    schedule 14.05.2011    source источник
comment
Ваш вопрос немного подробен, и я действительно не понимаю, о чем вы спрашиваете. В маршрутах rails вы можете сопоставлять маршруты с подстановочными знаками, но это не вопрос ruby-on-rails, даже если он помечен как один?   -  person oma    schedule 15.05.2011
comment
Маршрутизация рельсов работает, как и ожидалось; но Rails отвечает только для uris, начинающегося с /app. За пределами этого виртуального каталога находится приложение PHP, которое медленно, по частям, переносится на Rails. Я хочу, чтобы обработчик 404 отвечал за отсутствующие файлы PHP, отправляя их в Rails через ErrorDocument 404 /app/error/handle404. Это работает, за исключением того, что когда дескриптор действия ErrorController 404 фактически запускается, он не может увидеть исходный URL-адрес и, следовательно, не может понять, что делать с отсутствующей страницей.   -  person Matt Hucke    schedule 15.05.2011
comment
что может делать приложение rails? Кто отвечает за предоставление информации, php и/или apache? Я предлагаю вам переписать вопрос и иметь больше кода и конфигурации, если я буду тратить на это больше времени.   -  person oma    schedule 15.05.2011
comment
Приложение rails должно проверить исходный URL-адрес до ErrorDocument, а затем соответствующим образом направить его (используя регулярные выражения, поиск в базе данных и т. д., чтобы выяснить, что делать). Проблема в том, что я не могу получить доступ к этому URL-адресу (что-то вроде /does-not-exist.php); приложение rails видит только свой собственный URL-адрес post-ErrorDocument.   -  person Matt Hucke    schedule 15.05.2011


Ответы (1)


Поскольку я не смог найти исходный непереписанный URL-адрес в запросе Rails, я сделал это на PHP — простом, старомодном, не-фреймворковом PHP с явными вызовами mysqli_*().

Обработчик ошибок PHP получает необходимую информацию в хеше $_SERVER; $_SERVER['REQUEST_URI'] содержит исходный URI, который мне нужен.

Я просматриваю это в базе данных и, если нахожу соответствующую запись, выполняю перенаправление 301 на новое место; если записи нет, я просто показываю пользователю страницу 404.

Упрощенный (PHP):

$url = $_SERVER['REQUEST_URI'];
$redir = lookupRedirect($url);   # database stuff here
if (! $redir) {
    include ('404.phtml');
} else {
    header("Status: 301");
    header("Location: " . $redir['new_url']);
}

Это уродливый kluge, но я просто не мог найти способ сделать приложение Rails осведомленным об URL-адресе ошибки.

person Matt Hucke    schedule 18.05.2011