Class: ApiHammer::ContentTypeAttrs

Inherits:
Object
  • Object
show all
Defined in:
lib/api_hammer/content_type_attrs.rb

Overview

parses attributes out of content type header

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content_type) ⇒ ContentTypeAttrs

Returns a new instance of ContentTypeAttrs.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/api_hammer/content_type_attrs.rb', line 6

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

Instance Attribute Details

#content_typeObject (readonly)

Returns the value of attribute content_type.



32
33
34
# File 'lib/api_hammer/content_type_attrs.rb', line 32

def content_type
  @content_type
end

#media_typeObject (readonly)

Returns the value of attribute media_type.



32
33
34
# File 'lib/api_hammer/content_type_attrs.rb', line 32

def media_type
  @media_type
end

Instance Method Details

#[](key) ⇒ Object



38
39
40
# File 'lib/api_hammer/content_type_attrs.rb', line 38

def [](key)
  @attributes[key]
end

#parsed?Boolean

Returns:

  • (Boolean)


34
35
36
# File 'lib/api_hammer/content_type_attrs.rb', line 34

def parsed?
  @parsed
end

#text?Boolean

Returns:

  • (Boolean)


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/api_hammer/content_type_attrs.rb', line 42

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