File: querystring_builder.rb

package info (click to toggle)
ruby-aws-sdk-core 3.212.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,232 kB
  • sloc: ruby: 17,533; makefile: 4
file content (131 lines) | stat: -rw-r--r-- 3,760 bytes parent folder | download
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
# frozen_string_literal: true

module Aws
  module Rest
    module Request
      class QuerystringBuilder
        include Seahorse::Model::Shapes

        SUPPORTED_TYPES = [
          BooleanShape,
          FloatShape,
          IntegerShape,
          StringShape,
          TimestampShape
        ].freeze

        # Provide shape references and param values:
        #
        #     [
        #       [shape_ref1, 123],
        #       [shape_ref2, "text"]
        #     ]
        #
        # Returns a querystring:
        #
        #   "Count=123&Words=text"
        #
        # @param [Array<Array<Seahorse::Model::ShapeRef, Object>>] params An array of
        #   model shape references and request parameter value pairs.
        #
        # @return [String] Returns a built querystring
        def build(params)
          # keys in query maps must NOT override other keys
          query_keys = query_keys(params)
          params.map do |(shape_ref, param_value)|
            build_part(shape_ref, param_value, query_keys)
          end.reject { |p| p.nil? || p.empty? }.join('&')
        end

        private

        def query_keys(params)
          keys = Set.new
          params.each do |(shape_ref, _)|
            keys << shape_ref.location_name unless shape_ref.shape.is_a?(MapShape)
          end
          keys
        end

        def build_part(shape_ref, param_value, query_keys)
          case shape_ref.shape
          # supported scalar types
          when *SUPPORTED_TYPES
            "#{shape_ref.location_name}=#{query_value(shape_ref, param_value)}"
          when MapShape
            generate_query_map(shape_ref, param_value, query_keys)
          when ListShape
            generate_query_list(shape_ref, param_value)
          else
            raise NotImplementedError
          end
        end

        def timestamp(ref, value)
          case ref['timestampFormat'] || ref.shape['timestampFormat']
          when 'unixTimestamp' then value.to_i
          when 'rfc822' then value.utc.httpdate
          else
            # querystring defaults to iso8601
            value.utc.iso8601
          end
        end

        def query_value(ref, value)
          case ref.shape
          when TimestampShape
            escape(timestamp(ref, value))
          when *SUPPORTED_TYPES
            escape(value.to_s)
          else
            raise NotImplementedError
          end
        end

        def generate_query_list(ref, values)
          member_ref = ref.shape.member
          values.map do |value|
            value = query_value(member_ref, value)
            "#{ref.location_name}=#{value}"
          end
        end

        def generate_query_map(ref, value, query_keys)
          case ref.shape.value.shape
          when StringShape
            query_map_of_string(value, query_keys)
          when ListShape
            query_map_of_string_list(value, query_keys)
          else
            msg = 'Only map of string and string list supported'
            raise NotImplementedError, msg
          end
        end

        def query_map_of_string(hash, query_keys)
          list = []
          hash.each_pair do |key, value|
            key = escape(key)
            list << "#{key}=#{escape(value)}" unless query_keys.include?(key)
          end
          list
        end

        def query_map_of_string_list(hash, query_keys)
          list = []
          hash.each_pair do |key, values|
            key = escape(key)
            values.each do |value|
              list << "#{key}=#{escape(value)}" unless query_keys.include?(key)
            end
          end
          list
        end

        def escape(string)
          Seahorse::Util.uri_escape(string)
        end
      end
    end
  end
end