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

问题描述 投票:31回答:3

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

ruby http http-headers rack
3个回答
43
投票

传递给您的应用的Rack environment中提供了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

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


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]

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


2
投票

就像@ 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']
© www.soinside.com 2019 - 2024. All rights reserved.