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



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 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

Instance Attribute Details

#content_type ⇒ Object (readonly)

Returns the value of attribute content_type.



30
31
32
# File 'lib/api_hammer/content_type_attrs.rb', line 30

def content_type
  @content_type
end

#media_type ⇒ Object (readonly)

Returns the value of attribute media_type.



30
31
32
# File 'lib/api_hammer/content_type_attrs.rb', line 30

def media_type
  @media_type
end

Instance Method Details

#[](key) ⇒ Object



36
37
38
# File 'lib/api_hammer/content_type_attrs.rb', line 36

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

#parsed? ⇒ Boolean



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

def parsed?
  @parsed
end

#text? ⇒ Boolean



40
41
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
# 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