azure-storage 0.10.0.preview

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/lib/azure/storage.rb +58 -0
  3. data/lib/azure/storage/autoload.rb +71 -0
  4. data/lib/azure/storage/blob/append.rb +154 -0
  5. data/lib/azure/storage/blob/blob.rb +821 -0
  6. data/lib/azure/storage/blob/blob_service.rb +510 -0
  7. data/lib/azure/storage/blob/block.rb +264 -0
  8. data/lib/azure/storage/blob/container.rb +552 -0
  9. data/lib/azure/storage/blob/page.rb +380 -0
  10. data/lib/azure/storage/blob/serialization.rb +297 -0
  11. data/lib/azure/storage/client.rb +185 -0
  12. data/lib/azure/storage/configurable.rb +137 -0
  13. data/lib/azure/storage/core.rb +33 -0
  14. data/lib/azure/storage/core/auth/shared_access_signature.rb +27 -0
  15. data/lib/azure/storage/core/auth/shared_access_signature_generator.rb +194 -0
  16. data/lib/azure/storage/core/auth/shared_access_signature_signer.rb +49 -0
  17. data/lib/azure/storage/core/auth/shared_key.rb +125 -0
  18. data/lib/azure/storage/core/auth/shared_key_lite.rb +55 -0
  19. data/lib/azure/storage/core/auth/signer.rb +60 -0
  20. data/lib/azure/storage/core/autoload.rb +35 -0
  21. data/lib/azure/storage/core/client_options.rb +334 -0
  22. data/lib/azure/storage/core/client_options_error.rb +39 -0
  23. data/lib/azure/storage/core/constants.rb +1077 -0
  24. data/lib/azure/storage/core/error.rb +47 -0
  25. data/lib/azure/storage/core/filtered_service.rb +54 -0
  26. data/lib/azure/storage/core/http/debug_filter.rb +45 -0
  27. data/lib/azure/storage/core/http/http_error.rb +95 -0
  28. data/lib/azure/storage/core/http/http_filter.rb +62 -0
  29. data/lib/azure/storage/core/http/http_request.rb +182 -0
  30. data/lib/azure/storage/core/http/http_response.rb +105 -0
  31. data/lib/azure/storage/core/http/retry_policy.rb +83 -0
  32. data/lib/azure/storage/core/http/signer_filter.rb +42 -0
  33. data/lib/azure/storage/core/http_client.rb +63 -0
  34. data/lib/azure/storage/core/service.rb +55 -0
  35. data/lib/azure/storage/core/signed_service.rb +54 -0
  36. data/lib/azure/storage/core/sr.rb +83 -0
  37. data/lib/azure/storage/core/utility.rb +254 -0
  38. data/lib/azure/storage/queue/message.rb +39 -0
  39. data/lib/azure/storage/queue/queue.rb +37 -0
  40. data/lib/azure/storage/queue/queue_service.rb +580 -0
  41. data/lib/azure/storage/queue/serialization.rb +113 -0
  42. data/lib/azure/storage/service/access_policy.rb +35 -0
  43. data/lib/azure/storage/service/cors.rb +36 -0
  44. data/lib/azure/storage/service/cors_rule.rb +46 -0
  45. data/lib/azure/storage/service/enumeration_results.rb +30 -0
  46. data/lib/azure/storage/service/logging.rb +45 -0
  47. data/lib/azure/storage/service/metrics.rb +43 -0
  48. data/lib/azure/storage/service/retention_policy.rb +35 -0
  49. data/lib/azure/storage/service/serialization.rb +308 -0
  50. data/lib/azure/storage/service/signed_identifier.rb +39 -0
  51. data/lib/azure/storage/service/storage_service.rb +131 -0
  52. data/lib/azure/storage/service/storage_service_properties.rb +46 -0
  53. data/lib/azure/storage/table/auth/shared_key.rb +68 -0
  54. data/lib/azure/storage/table/auth/shared_key_lite.rb +53 -0
  55. data/lib/azure/storage/table/batch.rb +339 -0
  56. data/lib/azure/storage/table/batch_response.rb +127 -0
  57. data/lib/azure/storage/table/edmtype.rb +136 -0
  58. data/lib/azure/storage/table/entity.rb +40 -0
  59. data/lib/azure/storage/table/guid.rb +33 -0
  60. data/lib/azure/storage/table/query.rb +121 -0
  61. data/lib/azure/storage/table/serialization.rb +117 -0
  62. data/lib/azure/storage/table/table_service.rb +571 -0
  63. data/lib/azure/storage/version.rb +46 -0
  64. metadata +329 -0
@@ -0,0 +1,47 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ module Azure
25
+ module Core
26
+ # Superclass for errors generated from this library, so people can
27
+ # just rescue this for generic error handling
28
+ class Error < StandardError;end
29
+ end
30
+ end
31
+
32
+ module Azure::Storage
33
+ # Superclass for errors generated from this library, so people can
34
+ # just rescue this for generic error handling
35
+ class StorageError < StandardError
36
+ # attr_reader :description
37
+ # attr_reader :status_code
38
+ # attr_reader :type
39
+
40
+ # def initialize(description, type, status)
41
+ # @type = type
42
+ # @status_code = status
43
+ # @description = description
44
+ # super("#{type} (#{status_code}): #{description}")
45
+ # end
46
+ end
47
+ end
@@ -0,0 +1,54 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ require 'azure/storage/core/service'
25
+
26
+ module Azure
27
+ module Core
28
+ # A base class for Service implementations
29
+ class FilteredService < Service
30
+
31
+ # Create a new instance of the FilteredService
32
+ #
33
+ # @param host [String] The hostname. (optional, Default empty)
34
+ # @param options [Hash] options including {:client} (optional, Default {})
35
+ def initialize(host='', options={})
36
+ super
37
+ @filters = []
38
+ end
39
+
40
+ attr_accessor :filters
41
+
42
+ def call(method, uri, body=nil, headers=nil)
43
+ super(method, uri, body, headers) do |request|
44
+ filters.each { |filter| request.with_filter filter } if filters
45
+ end
46
+ end
47
+
48
+ def with_filter(filter=nil, &block)
49
+ filter = filter || block
50
+ filters.push filter if filter
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ require "azure/storage/core/http/http_filter"
25
+
26
+ module Azure
27
+ module Core
28
+ module Http
29
+ # A HttpFilter implementation that displays information about the request and response for debugging
30
+ class DebugFilter < HttpFilter
31
+ def call(req, _next)
32
+ puts "--REQUEST-BEGIN---------------------------"
33
+ puts "method:", req.method, "uri:", req.uri, "headers:", req.headers, "body:", req.body
34
+ puts "--REQUEST-END---------------------------"
35
+
36
+ r = _next.call
37
+ puts "--RESPONSE-BEGIN---------------------------"
38
+ puts "status_code:", r.status_code, "headers:", r.headers, "body:", r.body
39
+ puts "--RESPONSE-END---------------------------"
40
+ r
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,95 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ require 'azure/storage/core/error'
25
+
26
+ module Azure
27
+ module Core
28
+ module Http
29
+ # Public: Class for handling all HTTP response errors
30
+ class HTTPError < Azure::Core::Error
31
+
32
+ attr :uri
33
+
34
+ # Public: The HTTP status code of this error
35
+ #
36
+ # Returns a Fixnum
37
+ attr :status_code
38
+
39
+ # Public: The type of error
40
+ #
41
+ # http://msdn.microsoft.com/en-us/library/azure/dd179357
42
+ #
43
+ # Returns a String
44
+ attr :type
45
+
46
+ # Public: Description of the error
47
+ #
48
+ # Returns a String
49
+ attr :description
50
+
51
+ # Public: Detail of the error
52
+ #
53
+ # Returns a String
54
+ attr :detail
55
+
56
+ # Public: Initialize an error
57
+ #
58
+ # http_response - An Azure::Core::HttpResponse
59
+ def initialize(http_response)
60
+ @http_response = http_response
61
+ @uri = http_response.uri
62
+ @status_code = http_response.status_code
63
+ parse_response
64
+ super("#{type} (#{status_code}): #{description}")
65
+ end
66
+
67
+ # Extract the relevant information from the response's body. If the response
68
+ # body is not an XML, we return an 'Unknown' error with the entire body as
69
+ # the description
70
+ #
71
+ # Returns nothing
72
+ def parse_response
73
+ if @http_response.body && @http_response.body.include?('<')
74
+
75
+ document = Nokogiri.Slop(@http_response.body)
76
+
77
+ @type = document.css('code').first.text if document.css('code').any?
78
+ @type = document.css('Code').first.text if document.css('Code').any?
79
+ @description = document.css('message').first.text if document.css('message').any?
80
+ @description = document.css('Message').first.text if document.css('Message').any?
81
+
82
+ # service bus uses detail instead of message
83
+ @detail = document.css('detail').first.text if document.css('detail').any?
84
+ @detail = document.css('Detail').first.text if document.css('Detail').any?
85
+ else
86
+ @type = 'Unknown'
87
+ if @http_response.body
88
+ @description = "#{@http_response.body.strip}"
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,62 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ module Azure
25
+ module Core
26
+ module Http
27
+ # A filter which can modify the HTTP pipeline both before and
28
+ # after requests/responses. Multiple filters can be nested in a
29
+ # "Russian Doll" model to create a compound HTTP pipeline
30
+ class HttpFilter
31
+
32
+ # Initialize a HttpFilter
33
+ #
34
+ # &block - An inline block which implements the filter.
35
+ #
36
+ # The inline block should take parameters |request, _next| where
37
+ # request is a HttpRequest and _next is an object that implements
38
+ # a method .call which returns an HttpResponse. The block passed
39
+ # to the constructor should also return HttpResponse, either as
40
+ # the result of calling _next.call or by customized logic.
41
+ #
42
+ def initialize(&block)
43
+ @block = block
44
+ end
45
+
46
+ # Executes the filter
47
+ #
48
+ # request - HttpRequest. The request
49
+ # _next - An object that implements .call (no params)
50
+ #
51
+ # NOTE: _next is a either a subsequent HttpFilter wrapped in a
52
+ # closure, or the HttpRequest object's call method. Either way,
53
+ # it must have it's .call method executed within each filter to
54
+ # complete the pipeline. _next.call should return an HttpResponse
55
+ # and so should this Filter.
56
+ def call(request, _next)
57
+ @block ? @block.call(request, _next) : _next.call
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,182 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ require 'digest/md5'
25
+ require 'base64'
26
+ require 'net/http'
27
+ require 'time'
28
+
29
+ require 'azure/storage/version'
30
+ require 'azure/storage/core/http/http_response'
31
+ require 'azure/storage/core/constants'
32
+
33
+ module Azure
34
+ module Core
35
+ module Http
36
+ # Represents a HTTP request can perform synchronous queries to a
37
+ # HTTP server, returning a HttpResponse
38
+ class HttpRequest
39
+
40
+ alias_method :_method, :method
41
+
42
+ # The HTTP method to use (:get, :post, :put, :delete, etc...)
43
+ attr_accessor :method
44
+
45
+ # The URI of the HTTP endpoint to query
46
+ attr_accessor :uri
47
+
48
+ # The header values as a Hash
49
+ attr_accessor :headers
50
+
51
+ # The body of the request (IO or String)
52
+ attr_accessor :body
53
+
54
+ # Azure storage client which contains configuration context and http agents
55
+ # @return [Azure::Storage::Client]
56
+ attr_accessor :client
57
+
58
+ # Public: Create the HttpRequest
59
+ #
60
+ # @param method [Symbol] The HTTP method to use (:get, :post, :put, :del, etc...)
61
+ # @param uri [URI] The URI of the HTTP endpoint to query
62
+ # @param options_or_body [Hash|IO|String] The request options including {:client, :body} or raw body only
63
+ def initialize(method, uri, options_or_body = {})
64
+ options ||= unless options_or_body.is_a?(Hash)
65
+ {body: options_or_body}
66
+ end || options_or_body || {}
67
+
68
+ @method = method
69
+ @uri = if uri.is_a?(String)
70
+ URI.parse(uri)
71
+ else
72
+ uri
73
+ end
74
+
75
+ @client = options[:client] || Azure::Storage
76
+
77
+ self.headers = default_headers(options[:current_time] || Time.now.httpdate).merge(options[:headers] || {})
78
+ self.body = options[:body]
79
+ end
80
+
81
+ # Public: Applies a HttpFilter to the HTTP Pipeline
82
+ #
83
+ # filter - Any object that responds to .call(req, _next) and
84
+ # returns a HttpResponse eg. HttpFilter, Proc,
85
+ # lambda, etc. (optional)
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, &block)
101
+ filter = filter || block
102
+ if filter
103
+ old_impl = self._method(:call)
104
+
105
+ # support 1.8.7 (define_singleton_method doesn't exist until 1.9.1)
106
+ new_impl = Proc.new do
107
+ filter.call(self, old_impl)
108
+ end
109
+ k = class << self;
110
+ self;
111
+ end
112
+ if k.method_defined? :define_singleton_method
113
+ self.define_singleton_method(:call, new_impl)
114
+ else
115
+ k.send(:define_method, :call, new_impl)
116
+ end
117
+ end
118
+ end
119
+
120
+ # Build a default headers Hash
121
+ def default_headers(current_time)
122
+ {}.tap do |def_headers|
123
+ def_headers['User-Agent'] = Azure::Storage::Default::USER_AGENT
124
+ def_headers['x-ms-date'] = current_time
125
+ def_headers['x-ms-version'] = Azure::Storage::Default::STG_VERSION
126
+ def_headers['DataServiceVersion'] = '1.0;NetFx'
127
+ def_headers['MaxDataServiceVersion'] = '3.0;NetFx'
128
+ def_headers['Content-Type'] = 'application/atom+xml; charset=utf-8'
129
+ end
130
+ end
131
+
132
+ def http_setup
133
+ http = @client.agents(uri)
134
+ unless headers.nil?
135
+ keep_alive = headers['Keep-Alive'] || headers['keep-alive']
136
+ http.read_timeout = keep_alive.split('=').last.to_i unless keep_alive.nil?
137
+ end
138
+
139
+ http
140
+ end
141
+
142
+ def body=(body)
143
+ @body = body
144
+ apply_body_headers
145
+ end
146
+
147
+ # Sends request to HTTP server and returns a HttpResponse
148
+ #
149
+ # @return [HttpResponse]
150
+ def call
151
+ conn = http_setup
152
+ res = conn.run_request(method.to_sym, uri, nil, nil) do |req|
153
+ req.body = body if body
154
+ req.headers = headers if headers
155
+ end
156
+
157
+ response = HttpResponse.new(res)
158
+ response.uri = uri
159
+ raise response.error unless response.success?
160
+ response
161
+ end
162
+
163
+ private
164
+
165
+ def apply_body_headers
166
+ if body
167
+ if IO === body
168
+ headers['Content-Length'] = body.size.to_s
169
+ headers['Content-MD5'] = Digest::MD5.file(body.path).base64digest unless headers['Content-MD5']
170
+ else
171
+ headers['Content-Length'] = body.bytesize.to_s
172
+ headers['Content-MD5'] = Base64.strict_encode64(Digest::MD5.digest(body)) unless headers['Content-MD5']
173
+ end
174
+ else
175
+ headers['Content-Length'] = '0'
176
+ end
177
+ end
178
+
179
+ end
180
+ end
181
+ end
182
+ end