mss-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +9 -0
  3. data/LICENSE.txt +0 -0
  4. data/README.md +192 -0
  5. data/bin/mss-rb +178 -0
  6. data/ca-bundle.crt +3554 -0
  7. data/lib/mss/core/async_handle.rb +89 -0
  8. data/lib/mss/core/cacheable.rb +76 -0
  9. data/lib/mss/core/client.rb +786 -0
  10. data/lib/mss/core/collection/simple.rb +81 -0
  11. data/lib/mss/core/collection/with_limit_and_next_token.rb +70 -0
  12. data/lib/mss/core/collection/with_next_token.rb +96 -0
  13. data/lib/mss/core/collection.rb +262 -0
  14. data/lib/mss/core/configuration.rb +527 -0
  15. data/lib/mss/core/credential_providers.rb +653 -0
  16. data/lib/mss/core/data.rb +251 -0
  17. data/lib/mss/core/deprecations.rb +83 -0
  18. data/lib/mss/core/endpoints.rb +36 -0
  19. data/lib/mss/core/http/connection_pool.rb +374 -0
  20. data/lib/mss/core/http/curb_handler.rb +150 -0
  21. data/lib/mss/core/http/handler.rb +88 -0
  22. data/lib/mss/core/http/net_http_handler.rb +144 -0
  23. data/lib/mss/core/http/patch.rb +98 -0
  24. data/lib/mss/core/http/request.rb +258 -0
  25. data/lib/mss/core/http/response.rb +80 -0
  26. data/lib/mss/core/indifferent_hash.rb +87 -0
  27. data/lib/mss/core/inflection.rb +55 -0
  28. data/lib/mss/core/ini_parser.rb +41 -0
  29. data/lib/mss/core/json_client.rb +46 -0
  30. data/lib/mss/core/json_parser.rb +75 -0
  31. data/lib/mss/core/json_request_builder.rb +34 -0
  32. data/lib/mss/core/json_response_parser.rb +78 -0
  33. data/lib/mss/core/lazy_error_classes.rb +107 -0
  34. data/lib/mss/core/log_formatter.rb +426 -0
  35. data/lib/mss/core/managed_file.rb +31 -0
  36. data/lib/mss/core/meta_utils.rb +44 -0
  37. data/lib/mss/core/model.rb +61 -0
  38. data/lib/mss/core/naming.rb +29 -0
  39. data/lib/mss/core/option_grammar.rb +737 -0
  40. data/lib/mss/core/options/json_serializer.rb +81 -0
  41. data/lib/mss/core/options/validator.rb +154 -0
  42. data/lib/mss/core/options/xml_serializer.rb +117 -0
  43. data/lib/mss/core/page_result.rb +74 -0
  44. data/lib/mss/core/policy.rb +938 -0
  45. data/lib/mss/core/query_client.rb +40 -0
  46. data/lib/mss/core/query_error_parser.rb +23 -0
  47. data/lib/mss/core/query_request_builder.rb +46 -0
  48. data/lib/mss/core/query_response_parser.rb +34 -0
  49. data/lib/mss/core/region.rb +84 -0
  50. data/lib/mss/core/region_collection.rb +79 -0
  51. data/lib/mss/core/resource.rb +412 -0
  52. data/lib/mss/core/resource_cache.rb +39 -0
  53. data/lib/mss/core/response.rb +214 -0
  54. data/lib/mss/core/response_cache.rb +49 -0
  55. data/lib/mss/core/rest_error_parser.rb +23 -0
  56. data/lib/mss/core/rest_json_client.rb +39 -0
  57. data/lib/mss/core/rest_request_builder.rb +153 -0
  58. data/lib/mss/core/rest_response_parser.rb +65 -0
  59. data/lib/mss/core/rest_xml_client.rb +46 -0
  60. data/lib/mss/core/service_interface.rb +82 -0
  61. data/lib/mss/core/signers/base.rb +45 -0
  62. data/lib/mss/core/signers/cloud_front.rb +55 -0
  63. data/lib/mss/core/signers/s3.rb +158 -0
  64. data/lib/mss/core/signers/version_2.rb +71 -0
  65. data/lib/mss/core/signers/version_3.rb +85 -0
  66. data/lib/mss/core/signers/version_3_https.rb +60 -0
  67. data/lib/mss/core/signers/version_4/chunk_signed_stream.rb +190 -0
  68. data/lib/mss/core/signers/version_4.rb +227 -0
  69. data/lib/mss/core/uri_escape.rb +43 -0
  70. data/lib/mss/core/xml/frame.rb +245 -0
  71. data/lib/mss/core/xml/frame_stack.rb +84 -0
  72. data/lib/mss/core/xml/grammar.rb +306 -0
  73. data/lib/mss/core/xml/parser.rb +69 -0
  74. data/lib/mss/core/xml/root_frame.rb +64 -0
  75. data/lib/mss/core/xml/sax_handlers/libxml.rb +46 -0
  76. data/lib/mss/core/xml/sax_handlers/nokogiri.rb +55 -0
  77. data/lib/mss/core/xml/sax_handlers/ox.rb +40 -0
  78. data/lib/mss/core/xml/sax_handlers/rexml.rb +46 -0
  79. data/lib/mss/core/xml/stub.rb +122 -0
  80. data/lib/mss/core.rb +602 -0
  81. data/lib/mss/errors.rb +161 -0
  82. data/lib/mss/rails.rb +194 -0
  83. data/lib/mss/s3/access_control_list.rb +262 -0
  84. data/lib/mss/s3/acl_object.rb +263 -0
  85. data/lib/mss/s3/acl_options.rb +200 -0
  86. data/lib/mss/s3/bucket.rb +757 -0
  87. data/lib/mss/s3/bucket_collection.rb +161 -0
  88. data/lib/mss/s3/bucket_lifecycle_configuration.rb +472 -0
  89. data/lib/mss/s3/bucket_region_cache.rb +51 -0
  90. data/lib/mss/s3/bucket_tag_collection.rb +110 -0
  91. data/lib/mss/s3/bucket_version_collection.rb +78 -0
  92. data/lib/mss/s3/cipher_io.rb +119 -0
  93. data/lib/mss/s3/client/xml.rb +265 -0
  94. data/lib/mss/s3/client.rb +2076 -0
  95. data/lib/mss/s3/config.rb +60 -0
  96. data/lib/mss/s3/cors_rule.rb +107 -0
  97. data/lib/mss/s3/cors_rule_collection.rb +193 -0
  98. data/lib/mss/s3/data_options.rb +190 -0
  99. data/lib/mss/s3/encryption_utils.rb +145 -0
  100. data/lib/mss/s3/errors.rb +93 -0
  101. data/lib/mss/s3/multipart_upload.rb +353 -0
  102. data/lib/mss/s3/multipart_upload_collection.rb +75 -0
  103. data/lib/mss/s3/object_collection.rb +355 -0
  104. data/lib/mss/s3/object_metadata.rb +102 -0
  105. data/lib/mss/s3/object_upload_collection.rb +76 -0
  106. data/lib/mss/s3/object_version.rb +153 -0
  107. data/lib/mss/s3/object_version_collection.rb +88 -0
  108. data/lib/mss/s3/paginated_collection.rb +74 -0
  109. data/lib/mss/s3/policy.rb +73 -0
  110. data/lib/mss/s3/prefix_and_delimiter_collection.rb +46 -0
  111. data/lib/mss/s3/prefixed_collection.rb +84 -0
  112. data/lib/mss/s3/presign_v4.rb +135 -0
  113. data/lib/mss/s3/presigned_post.rb +574 -0
  114. data/lib/mss/s3/region_detection.rb +75 -0
  115. data/lib/mss/s3/request.rb +61 -0
  116. data/lib/mss/s3/s3_object.rb +1795 -0
  117. data/lib/mss/s3/tree/branch_node.rb +67 -0
  118. data/lib/mss/s3/tree/child_collection.rb +103 -0
  119. data/lib/mss/s3/tree/leaf_node.rb +93 -0
  120. data/lib/mss/s3/tree/node.rb +21 -0
  121. data/lib/mss/s3/tree/parent.rb +86 -0
  122. data/lib/mss/s3/tree.rb +115 -0
  123. data/lib/mss/s3/uploaded_part.rb +81 -0
  124. data/lib/mss/s3/uploaded_part_collection.rb +83 -0
  125. data/lib/mss/s3/website_configuration.rb +101 -0
  126. data/lib/mss/s3.rb +161 -0
  127. data/lib/mss/version.rb +16 -0
  128. data/lib/mss-sdk.rb +2 -0
  129. data/lib/mss.rb +14 -0
  130. data/rails/init.rb +14 -0
  131. metadata +201 -0
@@ -0,0 +1,374 @@
1
+ # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ #
8
+ # or in the "license" file accompanying this file. This file is
9
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
10
+ # ANY KIND, either express or implied. See the License for the specific
11
+ # language governing permissions and limitations under the License.
12
+
13
+ require 'net/http'
14
+ require 'net/https'
15
+ require 'thread'
16
+ require 'logger'
17
+
18
+ module MSS
19
+ module Core
20
+ module Http
21
+
22
+ # @attr_reader [URI::HTTP,nil] proxy_uri Returns the configured proxy uri.
23
+ # @attr_reader [Float,nil] http_continue_timeout
24
+ # @attr_reader [Integer,Float] http_idle_timeout
25
+ # @attr_reader [Integer,Float] http_open_timeout
26
+ # @attr_reader [Integer,Float] http_read_timeout
27
+ # @attr_reader [Boolean] http_wire_trace
28
+ # @attr_reader [Logger,nil] logger
29
+ # @attr_reader [Boolean] ssl_verify_peer
30
+ # @attr_reader [String,nil] ssl_ca_file
31
+ # @attr_reader [String,nil] ssl_ca_path
32
+ # @attr_reader [String,nil] ssl_cert_store
33
+ # @api private
34
+ class ConnectionPool
35
+
36
+ @pools_mutex = Mutex.new
37
+ @pools = {}
38
+
39
+ # @api private
40
+ OPTIONS = [
41
+ :proxy_uri,
42
+ :http_continue_timeout,
43
+ :http_idle_timeout,
44
+ :http_open_timeout,
45
+ :http_read_timeout,
46
+ :http_wire_trace,
47
+ :logger,
48
+ :ssl_verify_peer,
49
+ :ssl_ca_file,
50
+ :ssl_ca_path,
51
+ :ssl_cert_store,
52
+ ]
53
+
54
+ OPTIONS.each do |attr_name|
55
+ attr_reader(attr_name)
56
+ end
57
+
58
+ alias_method :http_wire_trace?, :http_wire_trace
59
+
60
+ alias_method :ssl_verify_peer?, :ssl_verify_peer
61
+
62
+ # @api private
63
+ def initialize options = {}
64
+ # user supplied options are filtered by the class .for method
65
+ options.each_pair do |opt_name, opt_value|
66
+ instance_variable_set("@#{opt_name}", opt_value)
67
+ end
68
+
69
+ # connection pool
70
+ @pool_mutex = Mutex.new
71
+ @pool = Hash.new do |pool,endpoint|
72
+ pool[endpoint] = []
73
+ pool[endpoint]
74
+ end
75
+ end
76
+
77
+ # @return [Hash] a read-only hash of options for this pool.
78
+ def options
79
+ OPTIONS.inject({}) do |options, opt_name|
80
+ options[opt_name] = send(opt_name)
81
+ options
82
+ end.freeze
83
+ end
84
+
85
+ # Makes an HTTP request, yielding a Net::HTTPResponse object.
86
+ #
87
+ # pool.request('http://google.com', Net::HTTP::Get.new('/')) do |resp|
88
+ # puts resp.code # status code
89
+ # puts resp.to_h.inspect # dump the headers
90
+ # puts resp.body
91
+ # end
92
+ #
93
+ # @param [URI::HTTP,URI::HTTPS,String] endpoint The HTTP(S) endpoint to
94
+ # connect to (e.g. 'https://domain.com').
95
+ #
96
+ # @param [Net::HTTPRequest] request The request to make. This can be
97
+ # any request object from Net::HTTP (e.g. Net::HTTP::Get,
98
+ # Net::HTTP::POST, etc).
99
+ #
100
+ # @yieldparam [Net::HTTPResponse] net_http_response
101
+ #
102
+ # @return (see #session_for
103
+ def request endpoint, request, &block
104
+ session_for(endpoint) do |http|
105
+ yield(http.request(request))
106
+ end
107
+ end
108
+
109
+ # @param [URI::HTTP,URI::HTTPS,String] endpoint The HTTP(S) endpoint to
110
+ # connect to (e.g. 'https://domain.com').
111
+ #
112
+ # @yieldparam [Net::HTTPSession] session
113
+ #
114
+ # @return [nil]
115
+ def session_for endpoint, &block
116
+ endpoint = endpoint.to_s
117
+ session = nil
118
+
119
+ # attempt to recycle an already open session
120
+ @pool_mutex.synchronize do
121
+ _clean
122
+ session = @pool[endpoint].shift
123
+ end
124
+
125
+ begin
126
+ session ||= start_session(endpoint)
127
+ session.read_timeout = http_read_timeout
128
+ session.continue_timeout = http_continue_timeout if
129
+ session.respond_to?(:continue_timeout=)
130
+ yield(session)
131
+ rescue Exception => error
132
+ session.finish if session
133
+ raise error
134
+ else
135
+ # No error raised? Good, check the session into the pool.
136
+ @pool_mutex.synchronize { @pool[endpoint] << session }
137
+ end
138
+ nil
139
+ end
140
+
141
+ # @return [Integer] Returns the count of sessions currently in the pool,
142
+ # not counting those currently in use.
143
+ def size
144
+ @pool_mutex.synchronize do
145
+ size = 0
146
+ @pool.each_pair do |endpoint,sessions|
147
+ size += sessions.size
148
+ end
149
+ size
150
+ end
151
+ end
152
+
153
+ # Removes stale http sessions from the pool (that have exceeded
154
+ # the idle timeout).
155
+ # @return [nil]
156
+ def clean!
157
+ @pool_mutex.synchronize { _clean }
158
+ nil
159
+ end
160
+
161
+ # Closes and removes removes all sessions from the pool.
162
+ # If empty! is called while there are outstanding requests they may
163
+ # get checked back into the pool, leaving the pool in a non-empty state.
164
+ # @return [nil]
165
+ def empty!
166
+ @pool_mutex.synchronize do
167
+ @pool.each_pair do |endpoint,sessions|
168
+ sessions.each(&:finish)
169
+ end
170
+ @pool.clear
171
+ end
172
+ nil
173
+ end
174
+
175
+ class << self
176
+
177
+ # Returns a connection pool constructed from the given options.
178
+ # Calling this method twice with the same options will return
179
+ # the same pool.
180
+ #
181
+ # @option options [URI::HTTP,String] :proxy_uri A proxy to send
182
+ # requests through. Formatted like 'http://proxy.com:123'.
183
+ #
184
+ # @option options [Float] :http_continue_timeout (nil) The number of
185
+ # seconds to wait for a 100-continue response before sending the
186
+ # request body. This option has no effect unless the request has
187
+ # "Expect" header set to "100-continue". Defaults to `nil` which
188
+ # disables this behaviour. This value can safely be set per-request
189
+ # on the session yeidled by {#session_for}.
190
+ #
191
+ # @option options [Float] :http_idle_timeout (15) The number of
192
+ # seconds a connection is allowed to sit idble before it is
193
+ # considered stale. Stale connections are closed and removed
194
+ # from the pool before making a request.
195
+ #
196
+ # @option options [Float] :http_open_timeout (15) The number of
197
+ # seconds to wait when opening a HTTP session before rasing a
198
+ # `Timeout::Error`.
199
+ #
200
+ # @option options [Integer] :http_read_timeout (60) The default
201
+ # number of seconds to wait for response data. This value can
202
+ # safely be set
203
+ # per-request on the session yeidled by {#session_for}.
204
+ #
205
+ # @option options [Boolean] :http_wire_trace (false) When `true`, HTTP
206
+ # debug output will be sent to the `:logger`.
207
+ #
208
+ # @option options [Logger] :logger Where debug output is sent.
209
+ # Defaults to `nil` when `:http_wire_trace` is `false`.
210
+ # Defaults to `Logger.new($stdout)` when `:http_wire_trace` is
211
+ # `true`.
212
+ #
213
+ # @option options [Boolean] :ssl_verify_peer (true) When `true`, SSL
214
+ # peer certificates are verified when establishing a connection.
215
+ #
216
+ # @option options [String] :ssl_ca_file Full path to the SSL
217
+ # certificate authority bundle file that should be used when
218
+ # verifying peer certificates. If you do not pass
219
+ # `:ssl_ca_file` or `:ssl_ca_path` the the system default will be
220
+ # used if available.
221
+ #
222
+ # @option options [String] :ssl_ca_path Full path of the directory
223
+ # that contains the unbundled SSL certificate authority files#
224
+ # for verifying peer certificates. If you do not pass
225
+ # `:ssl_ca_file` or `:ssl_ca_path` the the system default will
226
+ # be used if available.
227
+ #
228
+ # @option options [String] :ssl_cert_store
229
+ #
230
+ # @return [ConnectionPool]
231
+ def new options = {}
232
+ options = pool_options(options)
233
+ @pools_mutex.synchronize do
234
+ @pools[options] ||= build(options)
235
+ end
236
+ end
237
+
238
+ # Constructs and returns a new connection pool. This pool is never
239
+ # shared.
240
+ # @option (see new)
241
+ # @return [ConnectionPool]
242
+ def build(options = {})
243
+ pool = allocate
244
+ pool.send(:initialize, pool_options(options))
245
+ pool
246
+ end
247
+
248
+ # @return [Array<ConnectionPool>] Returns a list of of the constructed
249
+ # connection pools.
250
+ def pools
251
+ @pools.values
252
+ end
253
+
254
+ private
255
+
256
+ # Filters an option hash, merging in default values.
257
+ # @return [Hash]
258
+ def pool_options options
259
+ wire_trace = !!options[:http_wire_trace]
260
+ logger = options[:logger] || Logger.new($stdout) if wire_trace
261
+ verify_peer = options.key?(:ssl_verify_peer) ?
262
+ !!options[:ssl_verify_peer] : true
263
+ {
264
+ :proxy_uri => URI.parse(options[:proxy_uri].to_s),
265
+ :http_continue_timeout => options[:http_continue_timeout],
266
+ :http_open_timeout => options[:http_open_timeout] || 15,
267
+ :http_idle_timeout => options[:http_idle_timeout] || 15,
268
+ :http_read_timeout => options[:http_read_timeout] || 60,
269
+ :http_wire_trace => wire_trace,
270
+ :logger => logger,
271
+ :ssl_verify_peer => verify_peer,
272
+ :ssl_ca_file => options[:ssl_ca_file],
273
+ :ssl_ca_path => options[:ssl_ca_path],
274
+ :ssl_cert_store => options[:ssl_cert_store],
275
+ }
276
+ end
277
+
278
+ end
279
+
280
+ private
281
+
282
+ # Starts and returns a new HTTP(S) session.
283
+ # @param [String] endpoint
284
+ # @return [Net::HTTPSession]
285
+ def start_session endpoint
286
+
287
+ endpoint = URI.parse(endpoint)
288
+
289
+ args = []
290
+ args << endpoint.host
291
+ args << endpoint.port
292
+ args << proxy_uri.host
293
+ args << proxy_uri.port
294
+
295
+ if proxy_uri.user
296
+ args << URI::decode(proxy_uri.user)
297
+ else
298
+ args << nil
299
+ end
300
+
301
+ if proxy_uri.password
302
+ args << URI::decode(proxy_uri.password)
303
+ else
304
+ args << nil
305
+ end
306
+
307
+ http = Net::HTTP.new(*args.compact)
308
+ http.extend(SessionExtensions)
309
+ http.set_debug_output(logger) if http_wire_trace?
310
+ http.open_timeout = http_open_timeout
311
+
312
+ if endpoint.scheme == 'https'
313
+ http.use_ssl = true
314
+ if ssl_verify_peer?
315
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
316
+ http.ca_file = ssl_ca_file if ssl_ca_file
317
+ http.ca_path = ssl_ca_path if ssl_ca_path
318
+ http.cert_store = ssl_cert_store if ssl_cert_store
319
+ else
320
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
321
+ end
322
+ else
323
+ http.use_ssl = false
324
+ end
325
+
326
+ http.start
327
+ http
328
+ end
329
+
330
+ # Removes stale sessions from the pool. This method *must* be called
331
+ # @note **Must** be called behind a `@pool_mutex` synchronize block.
332
+ def _clean
333
+ now = Time.now
334
+ @pool.each_pair do |endpoint,sessions|
335
+ sessions.delete_if do |session|
336
+ if
337
+ session.last_used.nil? or
338
+ now - session.last_used > http_idle_timeout
339
+ then
340
+ session.finish
341
+ true
342
+ end
343
+ end
344
+ end
345
+ end
346
+
347
+ # Helper methods extended onto Net::HTTPSession objects opend by the
348
+ # connection pool.
349
+ # @api private
350
+ module SessionExtensions
351
+
352
+ # Sends the request and tracks that this session has been used.
353
+ def request *args, &block
354
+ @last_used = Time.now
355
+ super(*args, &block)
356
+ end
357
+
358
+ # @return [Time,nil]
359
+ def last_used
360
+ @last_used
361
+ end
362
+
363
+ # Attempts to close/finish the session without raising an error.
364
+ def finish
365
+ super
366
+ rescue IOError
367
+ nil
368
+ end
369
+
370
+ end
371
+ end
372
+ end
373
+ end
374
+ end
@@ -0,0 +1,150 @@
1
+ # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ #
8
+ # or in the "license" file accompanying this file. This file is
9
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
10
+ # ANY KIND, either express or implied. See the License for the specific
11
+ # language governing permissions and limitations under the License.
12
+
13
+ require 'thread'
14
+
15
+ module MSS
16
+ module Core
17
+ module Http
18
+
19
+ # @api private
20
+ class CurbHandler
21
+ class NetworkError < StandardError; end
22
+ def initialize
23
+ @q = []
24
+ @sem = Mutex.new
25
+ @multi = Curl::Multi.new
26
+
27
+ start_processor
28
+ end
29
+
30
+ def handle request, response, &read_block
31
+
32
+ raise "unsupport http reqest method: #{request.http_method}" unless
33
+ ['GET', 'HEAD', 'PUT', 'POST', 'DELETE'].include? request.http_method
34
+ @sem.synchronize do
35
+ @q << [request, response, read_block, Thread.current]
36
+ begin
37
+ @processor.wakeup
38
+ rescue ThreadError
39
+ start_processor
40
+ end
41
+ end
42
+ Thread.stop
43
+ nil
44
+ end
45
+
46
+ # fills the Curl::Multi handle with the given array of queue
47
+ # items, calling make_easy_handle on each one first
48
+ private
49
+ def fill_multi(items)
50
+ items.each do |item|
51
+ c = make_easy_handle(*item)
52
+ @multi.add(c)
53
+ end
54
+ end
55
+
56
+ # starts a background thread that waits for new items and
57
+ # sends them through the Curl::Multi handle
58
+ private
59
+ def start_processor
60
+ @processor = Thread.new do
61
+ loop do
62
+ items = nil
63
+ @sem.synchronize do
64
+ items = @q.slice!(0..-1)
65
+ end
66
+ unless items.empty?
67
+ fill_multi(items)
68
+ @multi.perform do
69
+ # curl is idle, so process more items if we can get them
70
+ # without blocking
71
+ if !@q.empty? && @sem.try_lock
72
+ begin
73
+ fill_multi(@q.slice!(0..-1))
74
+ ensure
75
+ @sem.unlock
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ # wait for a new item to show up before continuing
82
+ Thread.stop if @q.empty?
83
+ end
84
+ end
85
+ end
86
+
87
+ private
88
+ def make_easy_handle request, response, read_block, thread = nil
89
+
90
+ protocol = request.use_ssl? ? 'https' : 'http'
91
+ url = "#{protocol}://#{request.host}:#{request.port}#{request.uri}"
92
+
93
+ curl = Curl::Easy.new(url)
94
+ # curl.verbose = true
95
+ request.headers.each {|k, v| curl.headers[k] = v}
96
+
97
+ curl.on_header {|header_data|
98
+ if header_data =~ /:\s+/
99
+ name, value = header_data.strip.split(/:\s+/, 2)
100
+ response.headers[name] = value
101
+ end
102
+ header_data.length
103
+ }
104
+
105
+ case request.http_method
106
+ when 'GET'
107
+ # ....
108
+ when 'HEAD'
109
+ curl.head = true
110
+ when 'PUT'
111
+ curl.put_data = request.body || ''
112
+ when 'POST'
113
+ curl.headers['Content-Type'] = curl.headers['Content-Type'] || ''
114
+ curl.post_body = request.body || ''
115
+ when 'DELETE'
116
+ curl.delete = true
117
+ end
118
+
119
+ buffer = []
120
+
121
+ if read_block
122
+ curl.on_body do |chunk|
123
+ read_block.call(chunk)
124
+ chunk.size
125
+ end
126
+ else
127
+ curl.on_body do |chunk|
128
+ buffer << chunk
129
+ chunk.size
130
+ end
131
+ end
132
+
133
+ curl.on_complete do
134
+ response.status = curl.response_code
135
+ unless curl.response_code > 0
136
+ response.network_error = NetworkError.new('Empty response. Assume network error.')
137
+ end
138
+ unless read_block
139
+ response.body = buffer.join("")
140
+ end
141
+ thread.run if thread
142
+ end
143
+
144
+ curl
145
+ end
146
+
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,88 @@
1
+ # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ #
8
+ # or in the "license" file accompanying this file. This file is
9
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
10
+ # ANY KIND, either express or implied. See the License for the specific
11
+ # language governing permissions and limitations under the License.
12
+
13
+ module MSS
14
+ module Core
15
+ module Http
16
+
17
+ # @api private
18
+ class Handler
19
+
20
+ attr_reader :base
21
+
22
+ def initialize(base, &block)
23
+ @base = base
24
+ if base.respond_to?(:handle)
25
+
26
+ unless [2,3].include?(block.arity)
27
+ raise ArgumentError, 'passed block must accept 2 or 3 arguments'
28
+ end
29
+
30
+ MetaUtils.extend_method(self, :handle, &block)
31
+
32
+ if block.arity == 3
33
+ m = Module.new do
34
+ eval(<<-DEF)
35
+ def handle req, resp, &read_block
36
+ super(req, resp, read_block)
37
+ end
38
+ DEF
39
+ end
40
+ self.extend(m)
41
+ end
42
+
43
+ elsif base.respond_to?(:handle_async)
44
+
45
+ unless block.arity == 3
46
+ raise ArgumentError, 'passed block must accept 3 arguments'
47
+ end
48
+
49
+ MetaUtils.extend_method(self, :handle_async) do |req, resp, handle|
50
+ @base.handle_async(req, resp, handle)
51
+ end
52
+ MetaUtils.extend(self) do
53
+ define_method(:handle) do |req, resp|
54
+ raise "attempted to call #handle on an async handler"
55
+ end
56
+ define_method(:handle_async, &block)
57
+ end
58
+
59
+ else
60
+ raise ArgumentError, 'base must respond to #handle or #handle_async'
61
+ end
62
+ end
63
+
64
+ def handle(request, http_response, &read_block)
65
+ @base.handle(request, http_response, &read_block)
66
+ end
67
+
68
+ def handle_async(request, http_response, handle)
69
+ Thread.new do
70
+ begin
71
+ self.handle(request, http_response)
72
+ rescue => e
73
+ handle.signal_failure
74
+ else
75
+ handle.signal_success
76
+ end
77
+ end
78
+ end
79
+
80
+ def sleep_with_callback seconds, &block
81
+ Kernel.sleep(seconds)
82
+ yield
83
+ end
84
+
85
+ end
86
+ end
87
+ end
88
+ end