Программно обнаруживать и улавливать бесконечные петли перенаправления в Rails

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

У меня есть идея здесь, но мне все равно хотелось бы посмотреть, есть ли какие-либо проверенные методы.

Моя идея:

Переопределить Rails 'redirect_to в "log" перенаправления в сеансе:

def redirect_to(destination)
  session[:redirects] << {destination: destination, timestamp: Time.now}
  if is_inifinite_redirect?(session[:redirects])
    render "a_redirect_error_page"
  else
    super
  end
end

Затем сделайте некоторый анализ массива перенаправления, чтобы определить, существует ли бесконечный цикл:

def is_inifinite_redirect?(redirects)
  recent = redirects.last(21) # 21 is the max redirects allowed by Chrome
  return recent.odds.map(&:destination).uniq.length == 1 && \
    recent.evens.map(&:destination).uniq.length == 1 && \
    (recent.last.timestamp - recent.first.timestamp < 10.seconds)
end

Ответ 1

Я согласен с тем, что тесты должны теоретически препятствовать запуску в бесконечные циклы перенаправления. Но я понимаю, что тесты не являются ответом на ваш вопрос.

Я думаю, вы можете рассматривать бесконечный цикл переадресации, как только у вас есть две переадресации в строке с теми же аргументами. Я думаю, что нет веских оснований ждать новых переадресаций.

Моя идея - сохранить аргументы перенаправления в flash. Если аргументы в flash все те же, когда происходит следующее перенаправление, чем вы находитесь в цикле. Если произошла переадресация в другое место или была отображена обычная страница между ними, то это местоположение не будет совпадать или flash будет пустым:

def redirect_to(*args)
  if flash[:redirected_with_args] == args
    raise "Infinited redirect loop detected: #{args.inspect}"
  else
    flash[:redirected_with_args] = args
    super
  end
end

Ответ 2

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

Нет ничего плохого в добавлении кода, который вы получили выше, чтобы помочь вам отладить эту конкретную ситуацию (если это произойдет), но реальное решение здесь для производственного приложения - это провести тесты, чтобы вы не получали эти петли перенаправления.