标题非常明显。有没有办法获取标题(Rack::Request.env[]
除外)?
答案 0 :(得分:41)
传递给您应用的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哈希)。
答案 1 :(得分: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 :(得分:1)
类似于@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']