File: rest_request_builder.rb

package info (click to toggle)
ruby-aws-sdk 1.67.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,840 kB
  • sloc: ruby: 28,436; makefile: 7
file content (154 lines) | stat: -rw-r--r-- 4,420 bytes parent folder | download | duplicates (4)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

module AWS
  module Core

    # Given a hash of request options, a REST::RequestHandler can
    # populate a Core::Http::Request object.
    class RESTRequestBuilder

      # @api private
      def initialize operation, options = {}

        @http = operation[:http]
        @rules = operation[:inputs]

        @validator = Options::Validator.new(@rules)

        @serializer =
          case options[:format]
          when :xml
            namespace = options[:xmlnamespace]
            name = operation[:name]
            Options::XMLSerializer.new(namespace, name, operation)
          when :json
            Options::JSONSerializer.new(@rules, @http[:request_payload])
          else
            raise ArgumentError, "unhandled format: #{options[:format]}"
          end

      end

      # Populates a Http::Request with the following:
      #
      #   * HTTP method
      #   * URI
      #   * headers
      #   * body
      #
      # @param [Http::Request] request
      #
      # @param [Hash] params The hash of request options provided
      #   to the client request method.  This will be used to populate
      #   the headers, uri and body.
      #
      # @raise [ArgumentError] Raises ArgumentError when any of the
      #   request options are invalid (wrong type, missing, unknown, etc).
      #
      def populate_request request, params
        params = @validator.validate!(params)
        populate_method(request)
        populate_uri(request, params)
        populate_headers(request, params)
        populate_body(request, params)
      end

      private

      def populate_method request
        request.http_method = @http[:verb]
      end

      def populate_uri request, params
        request.uri = extract_uri(params)
      end

      def populate_headers request, params
        extract_headers(params).each_pair do |header_name, header_value|
          request.headers[header_name] = header_value
        end
      end

      # @param [Hash] params
      # @return [String]
      def extract_uri params

        path, querystring = @http[:uri].split(/\?/)

        uri = path.gsub(/:\w+/) do |param_name|
          if param = params.delete(param_name.sub(/^:/, '').to_sym)
            UriEscape.escape(param)
          else
            raise ArgumentError, "missing required option #{param_name}"
          end
        end

        querystring_parts = []
        querystring.to_s.split(/&|;/).each do |part|
          param_name = part.match(/:(\w+)/)[1]
          if param = params.delete(param_name.to_sym)
            param = UriEscape.escape(param)
            querystring_parts << part.sub(/:#{param_name}/, param)
          end
        end

        unless querystring_parts.empty?
          uri << "?#{querystring_parts.join('&')}"
        end

        uri

      end

      # @param [Hash] params
      # @return [Hash]
      def extract_headers params
        headers = {}
        (@http[:request_headers] || {}).each_pair do |param,header|
          headers[header] = params[param] if params.key?(param)
        end
        headers
      end

      # @param [Hash] params
      # @return [String,nil]
      def populate_body request, params
        if params.empty?
          request.body = nil
        elsif payload = streaming_param # streaming request
          request.body_stream = params[payload]
          request.headers['Content-Length'] = size(params[payload])
        else
          request.body = @serializer.serialize(params)
        end
      end

      def size(payload)
        if payload.respond_to?(:path) && payload.path
          File.size(payload.path)
        else
          payload.size
        end
      end

      def streaming_param
        if payload = @http[:request_payload]
          @rules[payload][:type] == :blob ? payload : nil
        end
      end

    end

  end
end