azure-storage-common 1.1.0 → 2.0.1

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 (60) hide show
  1. checksums.yaml +5 -5
  2. data/lib/azure/core.rb +47 -0
  3. data/lib/azure/core/auth/authorizer.rb +36 -0
  4. data/lib/azure/core/auth/shared_key.rb +125 -0
  5. data/lib/azure/core/auth/shared_key_lite.rb +48 -0
  6. data/lib/azure/core/auth/signer.rb +51 -0
  7. data/lib/azure/core/default.rb +23 -0
  8. data/lib/azure/core/error.rb +21 -0
  9. data/lib/azure/core/filtered_service.rb +45 -0
  10. data/lib/azure/core/http/debug_filter.rb +36 -0
  11. data/lib/azure/core/http/http_error.rb +135 -0
  12. data/lib/azure/core/http/http_filter.rb +53 -0
  13. data/lib/azure/core/http/http_request.rb +194 -0
  14. data/lib/azure/core/http/http_response.rb +102 -0
  15. data/lib/azure/core/http/retry_policy.rb +84 -0
  16. data/lib/azure/core/http/signer_filter.rb +33 -0
  17. data/lib/azure/core/service.rb +46 -0
  18. data/lib/azure/core/signed_service.rb +45 -0
  19. data/lib/azure/core/utility.rb +244 -0
  20. data/lib/azure/core/version.rb +33 -0
  21. data/lib/azure/http_response_helper.rb +38 -0
  22. data/lib/azure/storage/common.rb +26 -26
  23. data/lib/azure/storage/common/autoload.rb +62 -61
  24. data/lib/azure/storage/common/client.rb +162 -162
  25. data/lib/azure/storage/common/client_options.rb +363 -363
  26. data/lib/azure/storage/common/client_options_error.rb +41 -41
  27. data/lib/azure/storage/common/configurable.rb +212 -212
  28. data/lib/azure/storage/common/core.rb +35 -35
  29. data/lib/azure/storage/common/core/auth/anonymous_signer.rb +43 -43
  30. data/lib/azure/storage/common/core/auth/shared_access_signature.rb +30 -30
  31. data/lib/azure/storage/common/core/auth/shared_access_signature_generator.rb +399 -352
  32. data/lib/azure/storage/common/core/auth/shared_access_signature_signer.rb +57 -57
  33. data/lib/azure/storage/common/core/auth/shared_key.rb +60 -60
  34. data/lib/azure/storage/common/core/auth/token_signer.rb +43 -43
  35. data/lib/azure/storage/common/core/autoload.rb +53 -53
  36. data/lib/azure/storage/common/core/error.rb +43 -43
  37. data/lib/azure/storage/common/core/filter/exponential_retry_filter.rb +64 -64
  38. data/lib/azure/storage/common/core/filter/linear_retry_filter.rb +55 -55
  39. data/lib/azure/storage/common/core/filter/retry_filter.rb +300 -300
  40. data/lib/azure/storage/common/core/http_client.rb +79 -69
  41. data/lib/azure/storage/common/core/sr.rb +85 -85
  42. data/lib/azure/storage/common/core/token_credential.rb +64 -64
  43. data/lib/azure/storage/common/core/utility.rb +255 -255
  44. data/lib/azure/storage/common/default.rb +868 -868
  45. data/lib/azure/storage/common/service/access_policy.rb +37 -37
  46. data/lib/azure/storage/common/service/cors.rb +38 -38
  47. data/lib/azure/storage/common/service/cors_rule.rb +48 -48
  48. data/lib/azure/storage/common/service/enumeration_results.rb +32 -32
  49. data/lib/azure/storage/common/service/geo_replication.rb +40 -40
  50. data/lib/azure/storage/common/service/logging.rb +47 -47
  51. data/lib/azure/storage/common/service/metrics.rb +45 -45
  52. data/lib/azure/storage/common/service/retention_policy.rb +37 -37
  53. data/lib/azure/storage/common/service/serialization.rb +335 -335
  54. data/lib/azure/storage/common/service/signed_identifier.rb +40 -40
  55. data/lib/azure/storage/common/service/storage_service.rb +322 -322
  56. data/lib/azure/storage/common/service/storage_service_properties.rb +48 -48
  57. data/lib/azure/storage/common/service/storage_service_stats.rb +39 -39
  58. data/lib/azure/storage/common/service/user_delegation_key.rb +50 -0
  59. data/lib/azure/storage/common/version.rb +49 -49
  60. metadata +60 -18
@@ -0,0 +1,135 @@
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/error'
16
+ require 'nokogiri'
17
+ require 'json'
18
+
19
+ module Azure
20
+ module Core
21
+ module Http
22
+ # Public: Class for handling all HTTP response errors
23
+ class HTTPError < Azure::Core::Error
24
+
25
+ # Public: Detail of the response
26
+ #
27
+ # Returns an Azure::Core::Http::HttpResponse object
28
+ attr :http_response
29
+
30
+ # Public: The request URI
31
+ #
32
+ # Returns a String
33
+ attr :uri
34
+
35
+ # Public: The HTTP status code of this error
36
+ #
37
+ # Returns a Fixnum
38
+ attr :status_code
39
+
40
+ # Public: The type of error
41
+ #
42
+ # http://msdn.microsoft.com/en-us/library/azure/dd179357
43
+ #
44
+ # Returns a String
45
+ attr :type
46
+
47
+ # Public: Description of the error
48
+ #
49
+ # Returns a String
50
+ attr :description
51
+
52
+ # Public: Detail of the error
53
+ #
54
+ # Returns a String
55
+ attr :detail
56
+
57
+ # Public: The header name whose value is invalid
58
+ #
59
+ # Returns a String
60
+ attr :header
61
+
62
+ # Public: The invalid header value
63
+ #
64
+ # Returns a String
65
+ attr :header_value
66
+
67
+ # Public: Initialize an error
68
+ #
69
+ # http_response - An Azure::Core::HttpResponse
70
+ def initialize(http_response)
71
+ @http_response = http_response
72
+ @uri = http_response.uri
73
+ @status_code = http_response.status_code
74
+ parse_response
75
+ # Use reason phrase as the description if description is empty
76
+ @description = http_response.reason_phrase if (@description.nil? || @description.empty?) && http_response.reason_phrase
77
+ super("#{type} (#{status_code}): #{description}")
78
+ end
79
+
80
+ # Extract the relevant information from the response's body. If the response
81
+ # body is not an XML, we return an 'Unknown' error with the entire body as
82
+ # the description
83
+ #
84
+ # Returns nothing
85
+ def parse_response
86
+ if @http_response.body && @http_response.respond_to?(:headers) && @http_response.headers['Content-Type']
87
+ if @http_response.headers['Content-Type'].include?('xml')
88
+ parse_xml_response
89
+ elsif @http_response.headers['Content-Type'].include?('json')
90
+ parse_json_response
91
+ end
92
+ else
93
+ parse_unknown_response
94
+ end
95
+ end
96
+
97
+ def parse_xml_response
98
+ document = Nokogiri.Slop(@http_response.body)
99
+
100
+ @type = document.css('code').first.text if document.css('code').any?
101
+ @type = document.css('Code').first.text if document.css('Code').any?
102
+ @description = document.css('message').first.text if document.css('message').any?
103
+ @description = document.css('Message').first.text if document.css('Message').any?
104
+ @header = document.css('headername').first.text if document.css('headername').any?
105
+ @header = document.css('HeaderName').first.text if document.css('HeaderName').any?
106
+ @header_value = document.css('headervalue').first.text if document.css('headervalue').any?
107
+ @header_value = document.css('HeaderValue').first.text if document.css('HeaderValue').any?
108
+
109
+ # service bus uses detail instead of message
110
+ @detail = document.css('detail').first.text if document.css('detail').any?
111
+ @detail = document.css('Detail').first.text if document.css('Detail').any?
112
+ end
113
+
114
+ def parse_json_response
115
+ odata_error = JSON.parse(@http_response.body)['odata.error']
116
+ @type = odata_error['code']
117
+ @description = odata_error['message']['value']
118
+ end
119
+
120
+ def parse_unknown_response
121
+ @type = 'Unknown'
122
+ if @http_response.body
123
+ @description = "#{@http_response.body.strip}"
124
+ end
125
+ end
126
+
127
+ def inspect
128
+ string = "#<#{self.class.name}:#{self.object_id} "
129
+ fields = self.instance_variables.map{|field| "#{field}: #{self.send(field.to_s.delete("@")).inspect}"}
130
+ string << fields.join(", ") << ">"
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,53 @@
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
+ module Azure
16
+ module Core
17
+ module Http
18
+ # A filter which can modify the HTTP pipeline both before and
19
+ # after requests/responses. Multiple filters can be nested in a
20
+ # "Russian Doll" model to create a compound HTTP pipeline
21
+ class HttpFilter
22
+
23
+ # Initialize a HttpFilter
24
+ #
25
+ # &block - An inline block which implements the filter.
26
+ #
27
+ # The inline block should take parameters |request, _next| where
28
+ # request is a HttpRequest and _next is an object that implements
29
+ # a method .call which returns an HttpResponse. The block passed
30
+ # to the constructor should also return HttpResponse, either as
31
+ # the result of calling _next.call or by customized logic.
32
+ #
33
+ def initialize(&block)
34
+ @block = block
35
+ end
36
+
37
+ # Executes the filter
38
+ #
39
+ # request - HttpRequest. The request
40
+ # _next - An object that implements .call (no params)
41
+ #
42
+ # NOTE: _next is a either a subsequent HttpFilter wrapped in a
43
+ # closure, or the HttpRequest object's call method. Either way,
44
+ # it must have it's .call method executed within each filter to
45
+ # complete the pipeline. _next.call should return an HttpResponse
46
+ # and so should this Filter.
47
+ def call(request, _next)
48
+ @block ? @block.call(request, _next) : _next.call
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,194 @@
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
+
20
+ require 'azure/core/version'
21
+ require 'azure/core/http/http_response'
22
+ require 'azure/core/http/retry_policy'
23
+ require 'azure/core/default'
24
+ require 'azure/http_response_helper'
25
+
26
+ module Azure
27
+ module Core
28
+ module Http
29
+ # Represents a HTTP request can perform synchronous queries to a
30
+ # HTTP server, returning a HttpResponse
31
+ class HttpRequest
32
+ include Azure::HttpResponseHelper
33
+ alias_method :_method, :method
34
+
35
+ # The HTTP method to use (:get, :post, :put, :delete, etc...)
36
+ attr_accessor :method
37
+
38
+ # The URI of the HTTP endpoint to query
39
+ attr_accessor :uri
40
+
41
+ # The header values as a Hash
42
+ attr_accessor :headers
43
+
44
+ # The body of the request (IO or String)
45
+ attr_accessor :body
46
+
47
+ # Azure client which contains configuration context and http agents
48
+ # @return [Azure::Client]
49
+ attr_accessor :client
50
+
51
+ # The http filter
52
+ attr_accessor :has_retry_filter
53
+
54
+ # Public: Create the HttpRequest
55
+ #
56
+ # @param method [Symbol] The HTTP method to use (:get, :post, :put, :del, etc...)
57
+ # @param uri [URI] The URI of the HTTP endpoint to query
58
+ # @param options_or_body [Hash|IO|String] The request options including {:client, :body} or raw body only
59
+ def initialize(method, uri, options_or_body = {})
60
+ options ||= unless options_or_body.is_a?(Hash)
61
+ {body: options_or_body}
62
+ end || options_or_body || {}
63
+
64
+ @method = method
65
+ @uri = if uri.is_a?(String)
66
+ URI.parse(uri)
67
+ else
68
+ uri
69
+ end
70
+
71
+ @client = options[:client] || Azure
72
+
73
+ self.headers = default_headers(options[:current_time] || Time.now.httpdate).merge(options[:headers] || {})
74
+ self.body = options[:body]
75
+ end
76
+
77
+ # Public: Applies a HttpFilter to the HTTP Pipeline
78
+ #
79
+ # filter - Any object that responds to .call(req, _next) and
80
+ # returns a HttpResponse eg. HttpFilter, Proc,
81
+ # lambda, etc. (optional)
82
+ #
83
+ # options - The options that are used when call Azure::Core::FilteredService.call.
84
+ # It can be used by retry policies to determine changes in the retry.
85
+ #
86
+ # &block - An inline block may be used instead of a filter
87
+ #
88
+ # example:
89
+ #
90
+ # request.with_filter do |req, _next|
91
+ # _next.call
92
+ # end
93
+ #
94
+ # NOTE:
95
+ #
96
+ # The code block provided must call _next or the filter pipeline
97
+ # will not complete and the HTTP request will never execute
98
+ #
99
+ def with_filter(filter=nil, options={}, &block)
100
+ filter = filter || block
101
+ if filter
102
+ is_retry_policy = filter.is_a?(Azure::Core::Http::RetryPolicy)
103
+ filter.retry_data[:request_options] = options if is_retry_policy
104
+ @has_retry_filter ||= is_retry_policy
105
+
106
+ original_call = self._method(:call)
107
+
108
+ # support 1.8.7 (define_singleton_method doesn't exist until 1.9.1)
109
+ filter_call = Proc.new do
110
+ filter.call(self, original_call)
111
+ end
112
+ k = class << self;
113
+ self;
114
+ end
115
+ if k.method_defined? :define_singleton_method
116
+ self.define_singleton_method(:call, filter_call)
117
+ else
118
+ k.send(:define_method, :call, filter_call)
119
+ end
120
+ end
121
+ end
122
+
123
+ # Build a default headers Hash
124
+ def default_headers(current_time)
125
+ {}.tap do |def_headers|
126
+ def_headers['User-Agent'] = Azure::Core::Default::USER_AGENT
127
+ def_headers['x-ms-date'] = current_time
128
+ def_headers['x-ms-version'] = '2014-02-14'
129
+ def_headers['DataServiceVersion'] = '1.0;NetFx'
130
+ def_headers['MaxDataServiceVersion'] = '3.0;NetFx'
131
+ def_headers['Content-Type'] = 'application/atom+xml; charset=utf-8'
132
+ end
133
+ end
134
+
135
+ def http_setup
136
+ @client.agents(uri)
137
+ end
138
+
139
+ def body=(body)
140
+ @body = body
141
+ apply_body_headers
142
+ end
143
+
144
+ # Sends request to HTTP server and returns a HttpResponse
145
+ #
146
+ # @return [HttpResponse]
147
+ def call
148
+ conn = http_setup
149
+ res = set_up_response(method.to_sym, uri, conn, headers ,body)
150
+
151
+ response = HttpResponse.new(res)
152
+ response.uri = uri
153
+ raise response.error if !response.success? && !@has_retry_filter
154
+ response
155
+ end
156
+
157
+ private
158
+
159
+ def apply_body_headers
160
+ return headers['Content-Length'] = '0' unless body
161
+
162
+ return apply_io_headers if IO === body || Tempfile === body
163
+ return apply_string_io_headers if StringIO === body
164
+ return apply_miscellaneous_headers
165
+ end
166
+
167
+ def apply_io_headers
168
+ headers['Content-Length'] = body.size.to_s if body.respond_to?('size')
169
+ if headers['Content-Length'].nil?
170
+ raise ArgumentError, '\'Content-Length\' must be defined if size cannot be obtained from body IO.'
171
+ end
172
+ headers['Content-MD5'] = Digest::MD5.file(body.path).base64digest unless headers['Content-MD5']
173
+ end
174
+
175
+ def apply_string_io_headers
176
+ headers['Content-Length'] = body.size.to_s
177
+ unless headers['Content-MD5']
178
+ headers['Content-MD5'] = Digest::MD5.new.tap do |checksum|
179
+ while chunk = body.read(5242880)
180
+ checksum << chunk
181
+ end
182
+ body.rewind
183
+ end.base64digest
184
+ end
185
+ end
186
+
187
+ def apply_miscellaneous_headers
188
+ headers['Content-Length'] = body.size.to_s
189
+ headers['Content-MD5'] = Base64.strict_encode64(Digest::MD5.digest(body.to_s)) unless headers['Content-MD5']
190
+ end
191
+ end
192
+ end
193
+ end
194
+ 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