web-dev-qa-db-ja.com

Rack :: Request-すべてのヘッダーを取得するにはどうすればよいですか?

タイトルは一目瞭然です。ヘッダーを取得する方法はありますか(Rack::Request.env[]を除く)?

34
PJK

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

これを実行すると、ChromeまたはFirefoxで示されるHTTPヘッダーに加えて、「VERSION:HTPP/1.1」(つまり、キー「HTTP_VERSION」と値「HTTP /1.1 "がenvハッシュに追加されています)。

43
matt

@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]

主要な規則によっては、:capitalizeの代わりに他の何かを使用したい場合があります。

7
Gavriel

@Gavrielの回答に似ていますが、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']
2
Tyler Rick