require 'delegate' module M2R # Normalize headers access so that it is not case-sensitive # @api public class Headers include Enumerable # @param [Hash, #inject] hash Collection of headers # @param [true, false] compatible Whether the hash already contains # downcased strings only. If so it is going to be directly as # container for the headers. def initialize(hash = {}, compatible = false) @headers = hash and return if compatible @headers = hash.inject({}) do |headers,(header,value)| headers[transform_key(header)] = value headers end end # Get header # @param [String, Symbol, #to_s] header HTTP Header key # @return [String, nil] Value of given Header, nil when not present def [](header) @headers[transform_key(header)] end # Set header # @param [String, Symbol, #to_s] header HTTP Header key # @param [String] value HTTP Header value # @return [String] Set value def []=(header, value) @headers[transform_key(header)] = value end # Delete header # @param [String, Symbol, #to_s] header HTTP Header key # @return [String, nil] Value of deleted header, nil when was not present def delete(header) @headers.delete(transform_key(header)) end # Iterate over headers # @yield HTTP header and its value # @yieldparam [String] header HTTP Header name (downcased) # @yieldparam [String] value HTTP Header value # @return [Hash, Enumerator] def each(&proc) @headers.each(&proc) end # Fill Hash with Headers compatibile with Rack standard. # Every header except for Content-Length and Content-Type # is capitalized, underscored, and prefixed with HTTP. # Content-Length and Content-Type are not prefixed # (according to the spec) # # @param [Hash] env Hash representing Rack Env or compatible # @return [Hash] same Hash as provided as argument. def rackify(env = {}) @headers.each do |header, value| key = "HTTP_" + header.upcase.gsub("-", "_") env[key] = value end env["CONTENT_LENGTH"] = env.delete("HTTP_CONTENT_LENGTH") if env.key?("HTTP_CONTENT_LENGTH") env["CONTENT_TYPE"] = env.delete("HTTP_CONTENT_TYPE") if env.key?("HTTP_CONTENT_TYPE") env end def empty? @headers.empty? end protected def transform_key(key) key.to_s.downcase end end end