azure-storage-common 1.1.0 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +5 -5
  2. data/lib/azure/core/auth/authorizer.rb +36 -0
  3. data/lib/azure/core/auth/shared_key.rb +125 -0
  4. data/lib/azure/core/auth/shared_key_lite.rb +48 -0
  5. data/lib/azure/core/auth/signer.rb +51 -0
  6. data/lib/azure/core/default.rb +23 -0
  7. data/lib/azure/core/error.rb +21 -0
  8. data/lib/azure/core/filtered_service.rb +45 -0
  9. data/lib/azure/core/http/debug_filter.rb +36 -0
  10. data/lib/azure/core/http/http_error.rb +135 -0
  11. data/lib/azure/core/http/http_filter.rb +53 -0
  12. data/lib/azure/core/http/http_request.rb +195 -0
  13. data/lib/azure/core/http/http_response.rb +102 -0
  14. data/lib/azure/core/http/retry_policy.rb +84 -0
  15. data/lib/azure/core/http/signer_filter.rb +33 -0
  16. data/lib/azure/core/service.rb +46 -0
  17. data/lib/azure/core/signed_service.rb +45 -0
  18. data/lib/azure/core/utility.rb +244 -0
  19. data/lib/azure/core/version.rb +33 -0
  20. data/lib/azure/core.rb +47 -0
  21. data/lib/azure/http_response_helper.rb +38 -0
  22. data/lib/azure/storage/common/autoload.rb +62 -61
  23. data/lib/azure/storage/common/client.rb +162 -162
  24. data/lib/azure/storage/common/client_options.rb +363 -363
  25. data/lib/azure/storage/common/client_options_error.rb +41 -41
  26. data/lib/azure/storage/common/configurable.rb +212 -212
  27. data/lib/azure/storage/common/core/auth/anonymous_signer.rb +43 -43
  28. data/lib/azure/storage/common/core/auth/shared_access_signature.rb +30 -30
  29. data/lib/azure/storage/common/core/auth/shared_access_signature_generator.rb +399 -352
  30. data/lib/azure/storage/common/core/auth/shared_access_signature_signer.rb +57 -57
  31. data/lib/azure/storage/common/core/auth/shared_key.rb +60 -60
  32. data/lib/azure/storage/common/core/auth/token_signer.rb +43 -43
  33. data/lib/azure/storage/common/core/autoload.rb +53 -53
  34. data/lib/azure/storage/common/core/error.rb +43 -43
  35. data/lib/azure/storage/common/core/filter/exponential_retry_filter.rb +64 -64
  36. data/lib/azure/storage/common/core/filter/linear_retry_filter.rb +55 -55
  37. data/lib/azure/storage/common/core/filter/retry_filter.rb +300 -300
  38. data/lib/azure/storage/common/core/http_client.rb +82 -69
  39. data/lib/azure/storage/common/core/sr.rb +85 -85
  40. data/lib/azure/storage/common/core/token_credential.rb +64 -64
  41. data/lib/azure/storage/common/core/utility.rb +261 -255
  42. data/lib/azure/storage/common/core.rb +35 -35
  43. data/lib/azure/storage/common/default.rb +868 -868
  44. data/lib/azure/storage/common/service/access_policy.rb +37 -37
  45. data/lib/azure/storage/common/service/cors.rb +38 -38
  46. data/lib/azure/storage/common/service/cors_rule.rb +48 -48
  47. data/lib/azure/storage/common/service/enumeration_results.rb +32 -32
  48. data/lib/azure/storage/common/service/geo_replication.rb +40 -40
  49. data/lib/azure/storage/common/service/logging.rb +47 -47
  50. data/lib/azure/storage/common/service/metrics.rb +45 -45
  51. data/lib/azure/storage/common/service/retention_policy.rb +37 -37
  52. data/lib/azure/storage/common/service/serialization.rb +335 -335
  53. data/lib/azure/storage/common/service/signed_identifier.rb +40 -40
  54. data/lib/azure/storage/common/service/storage_service.rb +322 -322
  55. data/lib/azure/storage/common/service/storage_service_properties.rb +48 -48
  56. data/lib/azure/storage/common/service/storage_service_stats.rb +39 -39
  57. data/lib/azure/storage/common/service/user_delegation_key.rb +50 -0
  58. data/lib/azure/storage/common/version.rb +49 -49
  59. data/lib/azure/storage/common.rb +26 -26
  60. metadata +85 -17
@@ -0,0 +1,195 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ require 'digest/md5'
16
+ require 'base64'
17
+ require 'net/http'
18
+ require 'time'
19
+ require 'tempfile'
20
+
21
+ require 'azure/core/version'
22
+ require 'azure/core/http/http_response'
23
+ require 'azure/core/http/retry_policy'
24
+ require 'azure/core/default'
25
+ require 'azure/http_response_helper'
26
+
27
+ module Azure
28
+ module Core
29
+ module Http
30
+ # Represents a HTTP request can perform synchronous queries to a
31
+ # HTTP server, returning a HttpResponse
32
+ class HttpRequest
33
+ include Azure::HttpResponseHelper
34
+ alias_method :_method, :method
35
+
36
+ # The HTTP method to use (:get, :post, :put, :delete, etc...)
37
+ attr_accessor :method
38
+
39
+ # The URI of the HTTP endpoint to query
40
+ attr_accessor :uri
41
+
42
+ # The header values as a Hash
43
+ attr_accessor :headers
44
+
45
+ # The body of the request (IO or String)
46
+ attr_accessor :body
47
+
48
+ # Azure client which contains configuration context and http agents
49
+ # @return [Azure::Client]
50
+ attr_accessor :client
51
+
52
+ # The http filter
53
+ attr_accessor :has_retry_filter
54
+
55
+ # Public: Create the HttpRequest
56
+ #
57
+ # @param method [Symbol] The HTTP method to use (:get, :post, :put, :del, etc...)
58
+ # @param uri [URI] The URI of the HTTP endpoint to query
59
+ # @param options_or_body [Hash|IO|String] The request options including {:client, :body} or raw body only
60
+ def initialize(method, uri, options_or_body = {})
61
+ options ||= unless options_or_body.is_a?(Hash)
62
+ {body: options_or_body}
63
+ end || options_or_body || {}
64
+
65
+ @method = method
66
+ @uri = if uri.is_a?(String)
67
+ URI.parse(uri)
68
+ else
69
+ uri
70
+ end
71
+
72
+ @client = options[:client] || Azure
73
+
74
+ self.headers = default_headers(options[:current_time] || Time.now.httpdate).merge(options[:headers] || {})
75
+ self.body = options[:body]
76
+ end
77
+
78
+ # Public: Applies a HttpFilter to the HTTP Pipeline
79
+ #
80
+ # filter - Any object that responds to .call(req, _next) and
81
+ # returns a HttpResponse eg. HttpFilter, Proc,
82
+ # lambda, etc. (optional)
83
+ #
84
+ # options - The options that are used when call Azure::Core::FilteredService.call.
85
+ # It can be used by retry policies to determine changes in the retry.
86
+ #
87
+ # &block - An inline block may be used instead of a filter
88
+ #
89
+ # example:
90
+ #
91
+ # request.with_filter do |req, _next|
92
+ # _next.call
93
+ # end
94
+ #
95
+ # NOTE:
96
+ #
97
+ # The code block provided must call _next or the filter pipeline
98
+ # will not complete and the HTTP request will never execute
99
+ #
100
+ def with_filter(filter=nil, options={}, &block)
101
+ filter = filter || block
102
+ if filter
103
+ is_retry_policy = filter.is_a?(Azure::Core::Http::RetryPolicy)
104
+ filter.retry_data[:request_options] = options if is_retry_policy
105
+ @has_retry_filter ||= is_retry_policy
106
+
107
+ original_call = self._method(:call)
108
+
109
+ # support 1.8.7 (define_singleton_method doesn't exist until 1.9.1)
110
+ filter_call = Proc.new do
111
+ filter.call(self, original_call)
112
+ end
113
+ k = class << self;
114
+ self;
115
+ end
116
+ if k.method_defined? :define_singleton_method
117
+ self.define_singleton_method(:call, filter_call)
118
+ else
119
+ k.send(:define_method, :call, filter_call)
120
+ end
121
+ end
122
+ end
123
+
124
+ # Build a default headers Hash
125
+ def default_headers(current_time)
126
+ {}.tap do |def_headers|
127
+ def_headers['User-Agent'] = Azure::Core::Default::USER_AGENT
128
+ def_headers['x-ms-date'] = current_time
129
+ def_headers['x-ms-version'] = '2014-02-14'
130
+ def_headers['DataServiceVersion'] = '1.0;NetFx'
131
+ def_headers['MaxDataServiceVersion'] = '3.0;NetFx'
132
+ def_headers['Content-Type'] = 'application/atom+xml; charset=utf-8'
133
+ end
134
+ end
135
+
136
+ def http_setup
137
+ @client.agents(uri)
138
+ end
139
+
140
+ def body=(body)
141
+ @body = body
142
+ apply_body_headers
143
+ end
144
+
145
+ # Sends request to HTTP server and returns a HttpResponse
146
+ #
147
+ # @return [HttpResponse]
148
+ def call
149
+ conn = http_setup
150
+ res = set_up_response(method.to_sym, uri, conn, headers ,body)
151
+
152
+ response = HttpResponse.new(res)
153
+ response.uri = uri
154
+ raise response.error if !response.success? && !@has_retry_filter
155
+ response
156
+ end
157
+
158
+ private
159
+
160
+ def apply_body_headers
161
+ return headers['Content-Length'] = '0' unless body
162
+
163
+ return apply_io_headers if IO === body || Tempfile === body
164
+ return apply_string_io_headers if StringIO === body
165
+ return apply_miscellaneous_headers
166
+ end
167
+
168
+ def apply_io_headers
169
+ headers['Content-Length'] = body.size.to_s if body.respond_to?('size')
170
+ if headers['Content-Length'].nil?
171
+ raise ArgumentError, '\'Content-Length\' must be defined if size cannot be obtained from body IO.'
172
+ end
173
+ headers['Content-MD5'] = Digest::MD5.file(body.path).base64digest unless headers['Content-MD5']
174
+ end
175
+
176
+ def apply_string_io_headers
177
+ headers['Content-Length'] = body.size.to_s
178
+ unless headers['Content-MD5']
179
+ headers['Content-MD5'] = Digest::MD5.new.tap do |checksum|
180
+ while chunk = body.read(5242880)
181
+ checksum << chunk
182
+ end
183
+ body.rewind
184
+ end.base64digest
185
+ end
186
+ end
187
+
188
+ def apply_miscellaneous_headers
189
+ headers['Content-Length'] = body.size.to_s
190
+ headers['Content-MD5'] = Base64.strict_encode64(Digest::MD5.digest(body.to_s)) unless headers['Content-MD5']
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,102 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ require 'azure/core/http/http_error'
16
+
17
+ module Azure
18
+ module Core
19
+ module Http
20
+ # A small proxy to clean up the API of Net::HTTPResponse.
21
+ class HttpResponse
22
+ # Public: Initialize a new response.
23
+ #
24
+ # http_response - A Net::HTTPResponse.
25
+ def initialize(http_response, uri='')
26
+ @http_response = http_response
27
+ @uri = uri
28
+ end
29
+
30
+ attr_accessor :uri
31
+
32
+ # Public: Get the response body.
33
+ #
34
+ # Returns a String.
35
+ def body
36
+ @http_response.body
37
+ end
38
+
39
+ # Public: Get the response status code.
40
+ #
41
+ # Returns a Fixnum.
42
+ def status_code
43
+ @http_response.status
44
+ end
45
+
46
+ # Public: Get the response reason phrase.
47
+ #
48
+ # Returns a String.
49
+ def reason_phrase
50
+ @http_response.reason_phrase
51
+ end
52
+
53
+ # Public: Check if this response was successful. A request is considered
54
+ # successful if the response is in the 200 - 399 range.
55
+ #
56
+ # Returns nil|false.
57
+ def success?
58
+ @http_response.success?
59
+ end
60
+
61
+ # Public: Get all the response headers as a Hash.
62
+ #
63
+ # Returns a Hash.
64
+ def headers
65
+ @http_response.headers
66
+ end
67
+
68
+ # Public: Get an error that wraps this HTTP response, as long as this
69
+ # response was unsuccessful. This method will return nil if the
70
+ # response was successful.
71
+ #
72
+ # Returns an Azure::Core::Http::HTTPError.
73
+ def exception
74
+ HTTPError.new(self) unless success?
75
+ end
76
+
77
+ alias_method :error, :exception
78
+
79
+ # TODO: This needs to be deleted and HttpError needs to be refactored to not rely on HttpResponse.
80
+ # The dependency on knowing the internal structure of HttpResponse breaks good design principles.
81
+ # The only reason this class exists is because the HttpError parses the HttpResponse to produce an error msg.
82
+ class MockResponse
83
+ def initialize(code, body, headers)
84
+ @status = code
85
+ @body = body
86
+ @headers = headers
87
+ @headers.each { |k,v|
88
+ @headers[k] = [v] unless v.respond_to? 'first'
89
+ }
90
+ end
91
+ attr_accessor :status
92
+ attr_accessor :body
93
+ attr_accessor :headers
94
+
95
+ def to_hash
96
+ @headers
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,84 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ require "azure/core/http/http_filter"
16
+
17
+ module Azure
18
+ module Core
19
+ module Http
20
+
21
+ # A HttpFilter implementation that handles retrying based on a
22
+ # specific policy when HTTP layer errors occur
23
+ class RetryPolicy < HttpFilter
24
+
25
+ def initialize(&block)
26
+ @block = block
27
+ @retry_data = {}
28
+ end
29
+
30
+ attr_accessor :retry_data
31
+
32
+ # Overrides the base class implementation of call to implement
33
+ # a retry loop that uses should_retry? to determine when to
34
+ # break the loop
35
+ #
36
+ # req - HttpRequest. The HTTP request
37
+ # _next - HttpFilter. The next filter in the pipeline
38
+ def call(req, _next)
39
+ response = nil
40
+ retry_data = @retry_data.dup
41
+ begin
42
+ # URI could change in the retry, e.g. secondary endpoint
43
+ unless retry_data[:uri].nil?
44
+ req.uri = retry_data[:uri]
45
+ end
46
+
47
+ retry_data[:error] = nil
48
+ response = _next.call
49
+ rescue
50
+ retry_data[:error] = $!
51
+ end while should_retry?(response, retry_data)
52
+
53
+ # Assign the error when HTTP error is not thrown from the previous filter
54
+ retry_data[:error] = response.error if response && !response.success?
55
+ if retry_data[:error].nil?
56
+ response
57
+ else
58
+ raise retry_data[:error]
59
+ end
60
+ end
61
+
62
+ # Determines if the HTTP request should continue retrying
63
+ #
64
+ # response - HttpResponse. The response from the active request
65
+ # retry_data - Hash. Stores stateful retry data
66
+ #
67
+ # The retry_data is a Hash which can be used to store
68
+ # stateful data about the request execution context (such as an
69
+ # incrementing counter, timestamp, etc). The retry_data object
70
+ # will be the same instance throughout the lifetime of the request.
71
+ #
72
+ # If an inline block was passed to the constructor, that block
73
+ # will be used here and should return true to retry the job, or
74
+ # false to stop exit. If an inline block was not passed to the
75
+ # constructor the method returns false.
76
+ #
77
+ # Alternatively, a subclass could override this method.
78
+ def should_retry?(response, retry_data)
79
+ @block ? @block.call(response, retry_data) : false
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,33 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ require 'azure/core/http/http_filter'
16
+
17
+ module Azure
18
+ module Core
19
+ module Http
20
+ # A HttpFilter implementation that creates a authorization signature which is added to the request headers
21
+ class SignerFilter < HttpFilter
22
+ def initialize(signer)
23
+ @signer = signer
24
+ end
25
+
26
+ def call(req, _next)
27
+ @signer.sign_request(req)
28
+ _next.call
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,46 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ require 'azure/core/http/http_request'
16
+
17
+ module Azure
18
+ module Core
19
+ # A base class for Service implementations
20
+ class Service
21
+
22
+ # Create a new instance of the Service
23
+ #
24
+ # @param host [String] The hostname. (optional, Default empty)
25
+ # @param options [Hash] options including {:client} (optional, Default {})
26
+ def initialize(host='', options = {})
27
+ @host = host
28
+ @client = options[:client] || Azure
29
+ end
30
+
31
+ attr_accessor :host, :client
32
+
33
+ def call(method, uri, body=nil, headers={})
34
+ request = Core::Http::HttpRequest.new(method, uri, body: body, headers: headers, client: @client)
35
+ yield request if block_given?
36
+ request.call
37
+ end
38
+
39
+ def generate_uri(path='', query={})
40
+ uri = URI.parse(File.join(host, path))
41
+ uri.query = URI.encode_www_form(query) unless query == nil or query.empty?
42
+ uri
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,45 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ require 'azure/core/filtered_service'
16
+ require 'azure/core/http/signer_filter'
17
+ require 'azure/core/auth/shared_key'
18
+
19
+ module Azure
20
+ module Core
21
+ # A base class for Service implementations
22
+ class SignedService < FilteredService
23
+
24
+ # Create a new instance of the SignedService
25
+ #
26
+ # @param signer [Azure::Core::Auth::Signer]. An implementation of Signer used for signing requests. (optional, Default=Azure::Core::Auth::SharedKey.new)
27
+ # @param account_name [String] The account name (optional, Default=Azure.config.storage_account_name)
28
+ # @param options [Hash] options
29
+ def initialize(signer=nil, account_name=nil, options={})
30
+ super('', options)
31
+ signer ||= Core::Auth::SharedKey.new(client.storage_account_name, client.storage_access_key)
32
+ @account_name = account_name || client.storage_account_name
33
+ @signer = signer
34
+ filters.unshift Core::Http::SignerFilter.new(signer) if signer
35
+ end
36
+
37
+ attr_accessor :account_name
38
+ attr_accessor :signer
39
+
40
+ def call(method, uri, body=nil, headers=nil, options={})
41
+ super(method, uri, body, headers, options)
42
+ end
43
+ end
44
+ end
45
+ end