我希望有人可以为我清理一些东西。我正在使用Rails 2.3.5,我可以在控制器操作中访问请求标头,如下所示:
def index
if request.headers['...'] == '...'
...
end
end
或类似的东西。 request.headers是ActionController::Http::Headers的一个实例,它似乎是一个哈希。因此,我希望标题符合我发送的名称。但是,如果我使用Authorization标题发送请求,请执行以下操作:
curl -H 'Authorization: OAuth realm="MyRealm",...' http://app/path
操作中的以下代码返回false:
if request.headers.include?('Authorization') ...
以下回显我在标题中发送的值:
render :text => request.headers['Authorization']
以下检查返回true,有趣的是:
if request.headers.include?('HTTP_AUTHORIZATION') ...
同样,以下内容回显了我在标题中发送的值:
render :text => request.headers['HTTP_AUTHORIZATION']
似乎有一些我不知道的神奇事件。我完全混淆为什么检查密钥'授权'失败,但渲染request.headers ['Authorization']的值成功。我也很困惑'HTTP_AUTHORIZATION'来自哪里,因为不我正在发送请求的标头的名称。有谁知道究竟发生了什么?
答案 0 :(得分:29)
您是对的 - headers
ActionController::Request
方法返回ActionController::Http::Headers
的实例,该实例继承自Hash。如果我们打开源代码,我们会看到:
class Headers < ::Hash
extend ActiveSupport::Memoizable
def initialize(*args)
if args.size == 1 && args[0].is_a?(Hash)
super()
update(args[0])
else
super
end
end
def [](header_name)
if include?(header_name)
super
else
super(env_name(header_name))
end
end
private
# Converts a HTTP header name to an environment variable name.
def env_name(header_name)
"HTTP_#{header_name.upcase.gsub(/-/, '_')}"
end
memoize :env_name
end
因此,当通过[]
访问哈希时,会进行第二次检查,以确定是否存在来自env_name
的值(仅提升密钥和预先HTTP_
)。
这就是为什么你无法从request.headers.include?('Authorization')
获得真值的原因 - include?
未在子类中重写以检查标题的正常版本和更新版本。我想你可以效仿并自己实现:
module ActionController
module Http
class Headers < ::Hash
def include?(header_name)
self[header_name].present?
end
end
end
end
将其扔进lib/extensions/action_controller.rb
或其他内容,必要时在environment.rb
中要求它,你应该好好去。我建议您只修改控制器代码以使用[]
和present?
进行检查,但是:)
原因标题是大写的并且以HTTP_
为前缀,我相信,源于Rack,Rails的HTTP中间件。这可能是为了保持对案件的公正,另外在HTTP_
之前预先设置以避免与其他非标题环境内容冲突。
所以,是的,有点神奇,但在浏览源代码后不太难理解,我总是建议这样做:Rails有一些很好的资源,我多年来从中学到了很多东西。< / p>
答案 1 :(得分:5)
根据The Common Gateway Interface RFC:
名称以
"HTTP_"
开头的元变量包含值 如果使用的协议是,则从客户端请求头字段中读取 HTTP。 HTTP头字段名称转换为大写,具有 所有出现的"-"
都替换为"_"
且前缀为"HTTP_"
给出元变量名称。