Заголовок авторизации в Ruby on Rails получил доступ с ключевым HTTP_AUTHORIZATION вместо Авторизации?

Я надеюсь, что кто-то может разрешить что-то для меня. Я использую направляющие 2.3.5, и я могу получить доступ к заголовкам запроса в действии контроллера как это:

def index
  if request.headers['...'] == '...'
    ...
  end
end

Или что-то подобное. request.headers является экземпляром ActionController:: Http:: Заголовки, который, кажется, Хеш. Я ожидал бы, поэтому, что заголовки включаются на имени, которое я отправляю. Если я отправляю запрос однако, с заголовком Авторизации, как так:

curl -H 'Authorization: OAuth realm="MyRealm",...' http://app/path

Следующий код в действии возвращает false:

if request.headers.include?('Authorization') ... 

Принимая во внимание, что следующий echos значение я отправляю в заголовке:

render :text => request.headers['Authorization']

Следующая проверка возвращает true, интересно достаточно:

if request.headers.include?('HTTP_AUTHORIZATION') ... 

И точно так же следующее эхо значение я отправляю в заголовке:

render :text => request.headers['HTTP_AUTHORIZATION']

Кажется, что существует некоторое волшебство, происходящее это, я не знаю. Я полностью смущен относительно того, почему проверка ключевые сбои 'Авторизации', но рендеринг значения request.headers ['Авторизация'] успешно выполняется. Я также смущен как, туда, где 'HTTP_AUTHORIZATION' прибывает из того, поскольку это не название заголовка, я отправляю с запросом. Кто-либо знает то, что продолжается точно?

28
задан Lance Roberts 22 February 2010 в 16:55
поделиться

1 ответ

Вы правы - метод заголовков для 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 (которое просто увеличивает регистр ключа и добавляет ] HTTP_ ) существует.

Вот почему вы не можете получить истинное значение из request.headers.include? ('Авторизация') - 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, промежуточного программного обеспечения HTTP Rails. Вероятно, он делает это, чтобы оставаться беспристрастным к регистру, дополнительно добавляя HTTP_ , чтобы избежать конфликтов с другими входящими элементами среды, не являющимися заголовками.

Так что, да, немного волшебно, но не слишком сложно для понимания после взгляда на исходный код, который я всегда рекомендую :) У Rails есть очень хороший источник, из которого я многому научился за эти годы.

30
ответ дан 28 November 2019 в 03:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: