Module: Webmachine::Decision::Conneg

Included in:
Flow
Defined in:
lib/webmachine/decision/conneg.rb

Overview

Contains methods concerned with Content Negotiation, specifically, choosing media types, encodings, character sets and languages.

Defined Under Namespace

Classes: MediaTypeList, PriorityList

Constant Summary

HAS_ENCODING =

Ruby 1.9 compat

defined?(::Encoding)

Instance Method Summary (collapse)

Instance Method Details

- (Object) build_conneg_list(choices)

Given the choices in a conneg header, order them by appearance but also accounting for priority given by the client in the 'q' parameter.



82
83
84
85
86
87
# File 'lib/webmachine/decision/conneg.rb', line 82

def build_conneg_list(choices)
  choices.inject(PriorityList.new) do |acc, c|
    acc.add_header_val(c)
    acc
  end
end

- (Object) choose_charset(provided, header)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Given the 'Accept-Charset' header and provided charsets, chooses an appropriate charset.



47
48
49
50
51
52
53
54
55
56
# File 'lib/webmachine/decision/conneg.rb', line 47

def choose_charset(provided, header)
  if provided && !provided.empty?
    charsets = provided.map {|c| c.first }
    if charset = do_choose(charsets, header, HAS_ENCODING ? Encoding.default_external.name : kcode_charset)
      ['Charset'] = charset
    end
  else
    true
  end
end

- (Object) choose_encoding(provided, header)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Given the 'Accept-Encoding' header and provided encodings, chooses an appropriate encoding.



36
37
38
39
40
41
42
# File 'lib/webmachine/decision/conneg.rb', line 36

def choose_encoding(provided, header)
  encodings = provided.map {|p| p.first }
  if encoding = do_choose(encodings, header, "identity")
    response.headers['Content-Encoding'] = encoding unless encoding == 'identity'
    ['Content-Encoding'] = encoding
  end
end

- (Object) choose_media_type(provided, header)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Given the 'Accept' header and provided types, chooses an appropriate media type.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/webmachine/decision/conneg.rb', line 12

def choose_media_type(provided, header)
  requested = header.split(/\s*,\s*/).inject(MediaTypeList.new) do |acc, v|
    acc.add_header_val(v)
    acc
  end
  provided = provided.map do |p| # normalize_provided
    case p
    when String
      [p, {}]
    when Array
      p
    end
  end
  # choose_media_type1
  chosen = nil
  requested.each do |_, type_and_params|
    break if chosen = media_match(type_and_params, provided)             
  end
  format_content_type(*chosen) if chosen
end

- (Object) do_choose(choices, header, default)

Makes an conneg choice based what is accepted and what is provided.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/webmachine/decision/conneg.rb', line 59

def do_choose(choices, header, default)
  choices = choices.dup.map {|s| s.downcase }
  accepted = build_conneg_list(header.split(/\s*,\s/))
  default_priority = accepted.priority_of(default)
  star_priority = accepted.priority_of("*")
  default_ok = (default_priority.nil? && star_priority != 0.0) || default_priority
  any_ok = star_priority && star_priority > 0.0
  chosen = accepted.find do |priority, acceptable|
    if priority == 0.0
      choices.delete(acceptable.downcase)
      false
    else
      choices.include?(acceptable.downcase)
    end
  end
  (chosen && chosen.last) ||  # Use the matching one
    (any_ok && choices.first) || # Or first if "*"
    (default_ok && choices.include?(default) && default) # Or default
end