Rack :: Request - как мне получить все заголовки? - PullRequest
33 голосов
/ 11 июня 2011

Название довольно очевидно.Есть ли способ получить заголовки (кроме Rack::Request.env[])?

Ответы [ 3 ]

43 голосов
/ 12 июня 2011

Заголовки HTTP доступны в среде Rack , передаваемой вашему приложению:

HTTP_ Переменные: переменные, соответствующие предоставленным клиентом заголовкам HTTP-запроса (т. Е.переменные, имена которых начинаются с HTTP_).Наличие или отсутствие этих переменных должно соответствовать наличию или отсутствию соответствующего HTTP-заголовка в запросе.

Таким образом, заголовки HTTP имеют префикс «HTTP_» и добавляются в хеш.

Вот небольшая программа, которая извлекает и отображает их:

require 'rack'

app = Proc.new do |env|
  headers = env.select {|k,v| k.start_with? 'HTTP_'}
    .collect {|key, val| [key.sub(/^HTTP_/, ''), val]}
    .collect {|key, val| "#{key}: #{val}<br>"}
    .sort
  [200, {'Content-Type' => 'text/html'}, headers]
end

Rack::Server.start :app => app, :Port => 8080

Когда я запускаю это, в дополнение к заголовкам HTTP, как показано в Chrome или Firefox, появляется «VERSION: HTPP / 1.1»"(то есть запись с ключом" HTTP_VERSION "и значением" HTTP / 1.1 "добавляется в хеш env).

6 голосов
/ 20 октября 2015

На основе ответа @ matt, но это действительно дает вам заголовки запроса в хэше, как было запрошено в вопросе:

headers = Hash[*env.select {|k,v| k.start_with? 'HTTP_'}
  .collect {|k,v| [k.sub(/^HTTP_/, ''), v]}
  .collect {|k,v| [k.split('_').collect(&:capitalize).join('-'), v]}
  .sort
  .flatten]

В зависимости от того, какое ключевое соглашение вы предпочитаете, вы можете использовать что-то другое вместо: прописные.

2 голосов
/ 28 марта 2019

Как и ответ @ Гавриэля, но с использованием transform_keys (проще):

class Request
  def headers
    env.select { |k,v| k.start_with? 'HTTP_'}.
      transform_keys { |k| k.sub(/^HTTP_/, '').split('_').map(&:capitalize).join('-') }
  end
end

Вы можете даже сделать так, чтобы поиски продолжали работать, даже если случай отличается:

  def headers
    env.
      select { |k,v| k.start_with? 'HTTP_'}.
      transform_keys { |k| k.sub(/^HTTP_/, '').split('_').map(&:capitalize).join('-') }.
      sort.to_h.
      tap do |headers|
        headers.define_singleton_method :[] do |k|
          super(k.split(/[-_]/).map(&:capitalize).join('-'))
        end
      end
  end

Так, например, даже если headers нормализует ключи и возвращает следующее:

{
  Dnt: '1',
  Etag: 'W/"ec4454af5ae1bacff1afc5a06a2133f4"',
  'X-Xss-Protection': '1; mode=block',
}

вы все равно можете искать заголовки, используя более естественные / общие имена для этих заголовков:

headers['DNT']
headers['ETag']
headers['X-XSS-Protection']
...