class ApiHammer::ContentTypeAttrs

parses attributes out of content type header

Attributes

content_type[R]
media_type[R]

Public Class Methods

new(content_type) click to toggle source
# File lib/api_hammer/content_type_attrs.rb, line 4
def initialize(content_type)
  @media_type = (content_type.split(/\s*[;]\s*/, 2).first if content_type)
  @media_type.strip! if @media_type
  @content_type = content_type
  @parsed = false
  @attributes = Hash.new { |h,k| h[k] = [] }
  catch(:unparseable) do
    throw(:unparseable) unless content_type
    uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
    scanner = StringScanner.new(content_type)
    scanner.scan(/.*;\s*/) || throw(:unparseable)
    while scanner.scan(/(\w+)=("?)([^"]*)("?)\s*(,?)\s*/)
      key = scanner[1]
      quote1 = scanner[2]
      value = scanner[3]
      quote2 = scanner[4]
      comma_follows = !scanner[5].empty?
      throw(:unparseable) unless quote1 == quote2
      throw(:unparseable) if !comma_follows && !scanner.eos?
      @attributes[uri_parser.unescape(key)] << uri_parser.unescape(value)
    end
    throw(:unparseable) unless scanner.eos?
    @parsed = true
  end
end

Public Instance Methods

[](key) click to toggle source
# File lib/api_hammer/content_type_attrs.rb, line 36
def [](key)
  @attributes[key]
end
parsed?() click to toggle source
# File lib/api_hammer/content_type_attrs.rb, line 32
def parsed?
  @parsed
end
text?() click to toggle source
# File lib/api_hammer/content_type_attrs.rb, line 40
def text?
  # ordered hash by priority mapping types to binary or text
  # regexps will have \A and \z added
  types = {
    %r(image/.*) => :binary,
    %r(audio/.*) => :binary,
    %r(video/.*) => :binary,
    %r(model/.*) => :binary,
    %r(text/.*) => :text,
    %r(message/.*) => :text,
    %r(application/(.+\+)?json) => :text,
    %r(application/(.+\+)?xml) => :text,
    %r(model/(.+\+)?xml) => :text,
    'application/x-www-form-urlencoded' => :text,
    'application/javascript' => :text,
    'application/ecmascript' => :text,
    'application/octet-stream' => :binary,
    'application/ogg' => :binary,
    'application/pdf' => :binary,
    'application/postscript' => :binary,
    'application/zip' => :binary,
    'application/gzip' => :binary,
    'application/vnd.apple.pkpass' => :binary,
  }
  types.each do |match, type|
    matched = match.is_a?(Regexp) ? media_type =~ %r(\A#{match.source}\z) : media_type == match
    if matched
      return type == :text
    end
  end
  # fallback (unknown or not given) assume that unknown content types are binary but omitted
  # content-type means text
  if content_type && content_type =~ /\S/
    return false
  else
    return true
  end
end