File: http_utils.rb

package info (click to toggle)
ruby-sprockets 4.2.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,964 kB
  • sloc: ruby: 13,014; javascript: 157; makefile: 4
file content (135 lines) | stat: -rw-r--r-- 4,170 bytes parent folder | download | duplicates (2)
1
2
3
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
29
30
31
32
33
34
35
36
37
38
39
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# frozen_string_literal: true
module Sprockets
  # Internal: HTTP URI utilities. Many adapted from Rack::Utils. Mixed into
  # Environment.
  module HTTPUtils
    extend self

    # Public: Test mime type against mime range.
    #
    #    match_mime_type?('text/html', 'text/*') => true
    #    match_mime_type?('text/plain', '*') => true
    #    match_mime_type?('text/html', 'application/json') => false
    #
    # Returns true if the given value is a mime match for the given mime match
    # specification, false otherwise.
    def match_mime_type?(value, matcher)
      v1, v2 = value.split('/'.freeze, 2)
      m1, m2 = matcher.split('/'.freeze, 2)
      (m1 == '*'.freeze || v1 == m1) && (m2.nil? || m2 == '*'.freeze || m2 == v2)
    end

    # Public: Return values from Hash where the key matches the mime type.
    #
    # hash      - Hash of String matcher keys to Object values
    # mime_type - String mime type
    #
    # Returns Array of Object values.
    def match_mime_type_keys(hash, mime_type)
      type, subtype = mime_type.split('/', 2)
      [
        hash["*"],
        hash["*/*"],
        hash["#{type}/*"],
        hash["#{type}/#{subtype}"]
      ].compact
    end

    # Internal: Parse Accept header quality values.
    #
    # values - String e.g. "application/javascript"
    #
    # Adapted from Rack::Utils#q_values. Quality values are
    # described in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
    #
    #    parse_q_values("application/javascript")
    #      # => [["application/javascript", 1.0]]
    #
    #    parse_q_values("*/*")
    #      # => [["*/*", 1.0]]
    #
    #    parse_q_values("text/plain; q=0.5, image/*")
    #      # => [["text/plain", 0.5], ["image/*", 1.0]]
    #
    #    parse_q_values("application/javascript, text/css")
    #      # => [["application/javascript", 1.0], ["text/css", 1.0]]
    #
    # Returns an Array of [String, Float].
    def parse_q_values(values)
      values.to_s.split(/\s*,\s*/).map do |part|
        value, parameters = part.split(/\s*;\s*/, 2)
        quality = 1.0
        if md = /\Aq=([\d.]+)/.match(parameters)
          quality = md[1].to_f
        end
        [value, quality]
      end
    end

    # Internal: Find all qvalue matches from an Array of available options.
    #
    # Adapted from Rack::Utils#q_values.
    #
    # Returns Array of matched Strings from available Array or [].
    def find_q_matches(q_values, available, &matcher)
      matcher ||= lambda { |a, b| a == b }

      matches = []

      case q_values
      when Array
      when String
        q_values = parse_q_values(q_values)
      when NilClass
        q_values = []
      else
        raise TypeError, "unknown q_values type: #{q_values.class}"
      end

      i = 0
      q_values.each do |accepted, quality|
        if match = available.find { |option| matcher.call(option, accepted) }
          i += 1
          matches << [-quality, i, match]
        end
      end

      matches.sort!
      matches.map! { |_, _, match| match }
      matches
    end

    # Internal: Find the best qvalue match from an Array of available options.
    #
    # Adapted from Rack::Utils#q_values.
    #
    # Returns the matched String from available Array or nil.
    def find_best_q_match(q_values, available, &matcher)
      find_q_matches(q_values, available, &matcher).first
    end

    # Internal: Find the all qvalue match from an Array of available mime type
    # options.
    #
    # Adapted from Rack::Utils#q_values.
    #
    # Returns Array of matched mime type Strings from available Array or [].
    def find_mime_type_matches(q_value_header, available)
      find_q_matches(q_value_header, available) do |a, b|
        match_mime_type?(a, b)
      end
    end

    # Internal: Find the best qvalue match from an Array of available mime type
    # options.
    #
    # Adapted from Rack::Utils#q_values.
    #
    # Returns the matched mime type String from available Array or nil.
    def find_best_mime_type_match(q_value_header, available)
      find_best_q_match(q_value_header, available) do |a, b|
        match_mime_type?(a, b)
      end
    end
  end
end