Ответ 1
Вы правы - метод headers
ActionController::Request
возвращает экземпляр ActionController::Http::Headers
, который наследуется от Hash. Если мы раскроем исходный код, мы увидим следующее:
class Headers < ::Hash
extend ActiveSupport::Memoizable
def initialize(*args)
if args.size == 1 && args[0].is_a?(Hash)
super()
update(args[0])
else
super
end
end
def [](header_name)
if include?(header_name)
super
else
super(env_name(header_name))
end
end
private
# Converts a HTTP header name to an environment variable name.
def env_name(header_name)
"HTTP_#{header_name.upcase.gsub(/-/, '_')}"
end
memoize :env_name
end
Итак, при доступе к хэшу через []
, есть вторая проверка, чтобы увидеть, существует ли значение из env_name
(которое только увеличивает ключ и prepends HTTP_
).
Вот почему вы не можете получить истинное значение из request.headers.include?('Authorization')
- include?
не переопределяется в подклассе, чтобы проверить как нормальную, так и верхнюю версию заголовка. Я полагаю, вы могли бы последовать этому примеру и реализовать его так:
module ActionController
module Http
class Headers < ::Hash
def include?(header_name)
self[header_name].present?
end
end
end
end
Выбросьте это в lib/extensions/action_controller.rb
или что-то в этом случае, при необходимости, в environment.rb
, и вам должно быть хорошо идти. Я бы рекомендовал только изменить код вашего контроллера, чтобы использовать []
и present?
, чтобы выполнить проверку, хотя:)
Причина, по которой заголовки имеют верхний префикс и префикс HTTP_
, я полагаю, проистекает из промежуточного программного обеспечения Rack, Rails. Вероятно, это делает так, чтобы он оставался беспристрастным по отношению к делу, дополнительно добавляя HTTP_
, чтобы избежать конфликтов с другими материалами среды без заголовка, которые входят.
Итак, да, немного волшебный, но не слишком сложно понять, взглянув на источник, который я всегда рекомендую:) У Rails есть очень хороший источник, который я многому научился с годами.