Rack :: Request - 如何获取所有标题?

PJK*_*PJK 34 ruby rack http http-headers

标题非常明显.有没有办法获得标题(除了Rack::Request.env[])?

mat*_*att 43

传递给您的应用的Rack环境中提供了HTTP标头:

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
Run Code Online (Sandbox Code Playgroud)

当我运行它时,除了Chrome或Firefox所示的HTTP标头之外,还有一个"VERSION:HTPP/1.1"(即带有键"HTTP_VERSION"的条目和值"HTTP/1.1"正被添加到env中哈希值).

  • 啊,所以它基本上是`env`无论如何:).我不喜欢的是更新的名字,取代了一些字符.好吧,我想我必须侥幸逃脱.... (3认同)
  • @PJK我看到:`-`正在改为`_`.我想这是与CGI保持兼容(环境变量不能包含`-`).但_response_标头不应受到影响. (3认同)
  • 我知道,这只是一个方便的问题......例如,X-Build变成了HTTP_X_BUILD,这意味着X_Build和X-BUILD应该是等价的但是(我被告知)浏览器区分这两种选择. (2认同)

Gav*_*iel 6

基于@ 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]
Run Code Online (Sandbox Code Playgroud)

根据您喜欢的关键约定,您可能希望使用其他内容而不是:capitalize.


Tyl*_*ick 6

就像@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
Run Code Online (Sandbox Code Playgroud)

您甚至可以这样做,即使情况不同,查找仍然有效:

  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
Run Code Online (Sandbox Code Playgroud)

例如,即使headers标准化键,它也会返回:

{
  Dnt: '1',
  Etag: 'W/"ec4454af5ae1bacff1afc5a06a2133f4"',
  'X-Xss-Protection': '1; mode=block',
}
Run Code Online (Sandbox Code Playgroud)

您仍然可以使用这些标头的更自然/常见的名称来查找标头:

headers['DNT']
headers['ETag']
headers['X-XSS-Protection']
Run Code Online (Sandbox Code Playgroud)