cloudfiles 1.4.18 → 1.5.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.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ ================================================================================
2
+ 1.5.0 (2011/10/31
3
+ ================================================================================
4
+ o The underlying http wrapper now uses client.rb a simple abstraction to manage
5
+ each ReST call in its own function
6
+
1
7
  ================================================================================
2
8
  1.4.18 (2011/09/07)
3
9
  ================================================================================
@@ -31,3 +31,4 @@ CvX
31
31
  Topper Bowers
32
32
  Xavier Shay
33
33
  Dillon Amburgey
34
+ Scott Simpson
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  "TODO",
24
24
  "cloudfiles.gemspec",
25
25
  "lib/cloudfiles.rb",
26
+ "lib/client.rb",
26
27
  "lib/cloudfiles/authentication.rb",
27
28
  "lib/cloudfiles/connection.rb",
28
29
  "lib/cloudfiles/container.rb",
@@ -34,6 +35,7 @@ Gem::Specification.new do |s|
34
35
  "test/cloudfiles_connection_test.rb",
35
36
  "test/cloudfiles_container_test.rb",
36
37
  "test/cloudfiles_storage_object_test.rb",
38
+ "test/cloudfiles_client_test.rb",
37
39
  "test/test_helper.rb"
38
40
  ]
39
41
  s.homepage = %q{http://www.rackspacecloud.com/cloud_hosting_products/files}
@@ -47,21 +49,21 @@ Gem::Specification.new do |s|
47
49
  "test/cloudfiles_connection_test.rb",
48
50
  "test/cloudfiles_container_test.rb",
49
51
  "test/cloudfiles_storage_object_test.rb",
52
+ "test/cloudfiles_client_test.rb",
50
53
  "test/test_helper.rb"
51
54
  ]
52
55
 
56
+ s.add_dependency('json')
57
+
53
58
  if s.respond_to? :specification_version then
54
59
  s.specification_version = 3
55
60
 
56
61
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
- s.add_runtime_dependency(%q<mime-types>, [">= 1.16"])
58
62
  s.add_development_dependency(%q<mocha>, ["~> 0.9.8"])
59
63
  else
60
- s.add_dependency(%q<mime-types>, [">= 1.16"])
61
64
  s.add_dependency(%q<mocha>, ["~> 0.9.8"])
62
65
  end
63
66
  else
64
- s.add_dependency(%q<mime-types>, [">= 1.16"])
65
67
  s.add_dependency(%q<mocha>, ["~> 0.9.8"])
66
68
  end
67
69
  end
@@ -0,0 +1,620 @@
1
+ require 'rubygems'
2
+ require 'uri'
3
+ require 'json'
4
+
5
+ class ClientException < StandardError
6
+ attr_reader :scheme, :host, :port, :path, :query, :status, :reason, :devices
7
+ def initialize(msg, params={})
8
+ @msg = msg
9
+ @scheme = params[:http_scheme]
10
+ @host = params[:http_host]
11
+ @port = params[:http_port]
12
+ @path = params[:http_path]
13
+ @query = params[:http_query]
14
+ @status = params[:http_status]
15
+ @reason = params[:http_reason]
16
+ @device = params[:http_device]
17
+ end
18
+
19
+ def to_s
20
+ a = @msg
21
+ b = ''
22
+ b += "#{@scheme}://" if @scheme
23
+ b += @host if @host
24
+ b += ":#{@port}" if @port
25
+ b += @path if @path
26
+ b += "?#{@query}" if @query
27
+ b ? b = "#{b} #{@status}" : b = @status.to_s if @status
28
+ b ? b = "#{b} #{@reason}" : b = "- #{@reason}" if @reason
29
+ b ? b = "#{b}: device #{@device}" : b = "device #{@device}" if @device
30
+ b ? "#{a} #{b}" : a
31
+ end
32
+ end
33
+
34
+ class ChunkedConnectionWrapper
35
+ def initialize(data, chunk_size)
36
+ @size = chunk_size
37
+ if data.respond_to? :read
38
+ @file = data
39
+ end
40
+ end
41
+
42
+ def read(foo)
43
+ if @file
44
+ @file.read(@size)
45
+ end
46
+ end
47
+ def eof!
48
+ @file.eof!
49
+ end
50
+ def eof?
51
+ @file.eof?
52
+ end
53
+ end
54
+
55
+ def quote(value)
56
+ URI.encode(value)
57
+ end
58
+
59
+ class Query
60
+ def initialize(url_params)
61
+ if url_params
62
+ @params = Query.from_url_params(url_params)
63
+ else
64
+ @params = {}
65
+ end
66
+ end
67
+ def to_s
68
+ to_url_params
69
+ end
70
+ def to_url_params
71
+ elements = []
72
+ @params.each_pair {|k,v| elements << "#{k}=#{v}"}
73
+ elements.join('&')
74
+ end
75
+ def self.from_url_params(url_params)
76
+ result = {}
77
+ url_params.split('&').each do |element|
78
+ element = element.split('=')
79
+ result[element[0]] = element[1]
80
+ end
81
+ result
82
+ end
83
+ def has_key?(key)
84
+ @params.has_key? key
85
+ end
86
+ def add(key, value)
87
+ @params[key] = value
88
+ end
89
+ def delete(key)
90
+ @params.delete(key)
91
+ end
92
+ end
93
+
94
+ class SwiftClient
95
+ def initialize(authurl, user, key, retries=5, preauthurl=nil, preauthtoken=nil, snet=false, starting_backoff=1)
96
+ @authurl = authurl
97
+ @user = user
98
+ @key = key
99
+ @retries = retries
100
+ @http_conn = nil
101
+ @url = preauthurl
102
+ @token = preauthtoken
103
+ @attempts = 0
104
+ @snet = snet
105
+ @starting_backoff = starting_backoff
106
+ end
107
+
108
+ private
109
+ def _retry(reset, func, args=nil)
110
+ @attempts = 0
111
+ backoff = @starting_backoff
112
+
113
+ while @attempts < @retries
114
+ @attempts += 1
115
+ begin
116
+ if !@url or !@token
117
+ @url, @token = self.get_auth()
118
+ @http_conn = nil
119
+ end
120
+ @http_conn = self.http_connection() if !@http_conn
121
+ return SwiftClient.method(func).call(@url, @token, *args)
122
+ rescue Net::HTTPExceptions
123
+ if @attempts > @retries
124
+ raise
125
+ end
126
+ @http_conn = nil
127
+ rescue ClientException => err
128
+ if @attempts > @retries
129
+ raise
130
+ end
131
+ if err.status.to_i == 401
132
+ @url = @token = nil
133
+ if @attempts > 1
134
+ raise
135
+ end
136
+ elsif err.status.to_i == 408
137
+ @http_conn = nil
138
+ elsif err.status.to_i >= 500 and err.status.to_i <= 599
139
+ return nil
140
+ else
141
+ raise
142
+ end
143
+ end
144
+ sleep(backoff)
145
+ backoff *= 2
146
+ if reset
147
+ reset.call(args)
148
+ end
149
+ end
150
+ end
151
+
152
+ public
153
+ def self.http_connection(url, proxy_host=nil, proxy_port=nil)
154
+ parsed = URI::parse(url)
155
+
156
+ if parsed.scheme == 'http'
157
+ require 'net/http'
158
+ conn = Net::HTTP::Proxy(proxy_host, proxy_port).new(parsed.host, parsed.port)
159
+ [parsed, conn]
160
+ elsif parsed.scheme == 'https'
161
+ require 'net/https'
162
+ conn = Net::HTTP::Proxy(proxy_host, proxy_port).new(parsed.host, parsed.port)
163
+ conn.use_ssl = true
164
+ conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
165
+ [parsed, conn]
166
+ else
167
+ raise ClientException.new(
168
+ "Cannot handle protocol scheme #{parsed.scheme} for #{url} %s")
169
+ end
170
+ end
171
+
172
+ def http_connection
173
+ if !@http_conn
174
+ @http_conn = SwiftClient.http_connection(@url)
175
+ else
176
+ @http_conn
177
+ end
178
+ end
179
+
180
+ def self.get_auth(url, user, key, snet=false)
181
+ parsed, conn = http_connection(url)
182
+ conn.start if not conn.started?
183
+ resp = conn.get(URI.encode(parsed.request_uri), {"x-auth-user" => user, "x-auth-key" => key })
184
+ if resp.code.to_i < 200 or resp.code.to_i > 300
185
+ raise ClientException.new('Account GET failed', :http_scheme=>parsed.scheme,
186
+ :http_host=>conn.address, :http_port=>conn.port,
187
+ :http_path=>parsed.path, :http_query=>parsed.query, :http_status=>resp.code,
188
+ :http_reason=>resp.message)
189
+ end
190
+ url = URI::parse(resp.header['x-storage-url'])
191
+ if snet
192
+ url.host = "snet-#{url.host}"
193
+ end
194
+ [url.to_s, resp.header['x-auth-token'], resp.header]
195
+ end
196
+
197
+ def get_auth
198
+ @url, @token = SwiftClient.get_auth(@authurl, @user, @key, @snet)
199
+ end
200
+
201
+ def self.get_account(url, token, marker=nil, limit=nil, prefix=nil,
202
+ http_conn=nil, full_listing=false)
203
+ #todo: add in rest of functionality
204
+ if not http_conn
205
+ http_conn = http_connection(url)
206
+ end
207
+ parsed = http_conn[0].clone
208
+ conn = http_conn[1]
209
+ if full_listing
210
+ rv = get_account(url, token, marker, limit, prefix, http_conn)
211
+ listing = rv[1]
212
+ while listing.length > 0
213
+ marker = listing[-1]['name']
214
+ listing = get_account(url, token, marker, limit, prefix, http_conn)[1]
215
+ if listing.length > 0
216
+ rv[1] += listing
217
+ end
218
+ end
219
+ return rv
220
+ end
221
+ query = Query.new(parsed.query)
222
+ query.add('format', 'json')
223
+ query.add('marker', quote(marker.to_s)) if marker
224
+ query.add('limit', quote(limit.to_s)) if limit
225
+ query.add('prefix', quote(prefix.to_s)) if prefix
226
+ parsed.query = query.to_url_params
227
+ conn.start if !conn.started?
228
+ resp = conn.get(parsed.request_uri, {'x-auth-token' => token})
229
+ if resp.code.to_i < 200 or resp.code.to_i > 300
230
+ raise ClientException.new('Account GET failed', :http_scheme=>parsed.scheme,
231
+ :http_host=>conn.address, :http_port=>conn.port,
232
+ :http_path=>parsed.path, :http_query=>parsed.query, :http_status=>resp.code,
233
+ :http_reason=>resp.message)
234
+ end
235
+ resp_headers = {}
236
+ resp.header.each do |k,v|
237
+ resp_headers[k.downcase] = v
238
+ end
239
+ if resp.code.to_i == 204
240
+ [resp_headers, []]
241
+ else
242
+ [resp_headers, JSON.parse(resp.body)]
243
+ end
244
+ end
245
+
246
+ def get_account(marker=nil, limit=nil, prefix=nil, full_listing=false)
247
+ _retry(nil, :get_account, [marker, limit, prefix, @http_conn, full_listing])
248
+ end
249
+
250
+ def self.head_account(url, token, http_conn=nil)
251
+ if not http_conn
252
+ http_conn = http_connection(url)
253
+ end
254
+ parsed = http_conn[0].clone
255
+ conn = http_conn[1]
256
+ conn.start if !conn.started?
257
+ resp = conn.head(parsed.request_uri, {'x-auth-token' => token})
258
+ if resp.code.to_i < 200 or resp.code.to_i > 300
259
+ raise ClientException.new('Account HEAD failed', :http_scheme=>parsed.scheme,
260
+ :http_host=>conn.address, :http_port=>conn.port,
261
+ :http_path=>parsed.path, :http_status=>resp.code,
262
+ :http_reason=>resp.message)
263
+ end
264
+ resp_headers = {}
265
+ resp.header.each do |k,v|
266
+ resp_headers[k.downcase] = v
267
+ end
268
+ resp_headers
269
+ end
270
+
271
+ def head_account
272
+ _retry(nil, :head_account, [@http_conn])
273
+ end
274
+
275
+ def self.post_account(url, token, headers, http_conn=nil)
276
+ if not http_conn
277
+ http_conn = http_connection(url)
278
+ end
279
+ parsed = http_conn[0].clone
280
+ conn = http_conn[1]
281
+ headers['x-auth-token'] = token
282
+ conn.start if !conn.started?
283
+ resp = conn.post(parsed.request_uri, nil, headers)
284
+ if resp.code.to_i < 200 or resp.code.to_i > 300
285
+ raise ClientException.new('Account POST failed', :http_scheme=>parsed.scheme,
286
+ :http_host=>conn.address, :http_port=>conn.port,
287
+ :http_path=>parsed.path, :http_status=>resp.code,
288
+ :http_reason=>resp.message)
289
+ end
290
+ resp.body
291
+ end
292
+ def post_account(headers=nil)
293
+ _retry(nil, :post_account, [headers, @http_conn])
294
+ end
295
+
296
+ def self.get_container(url, token, container, marker=nil, limit=nil,
297
+ prefix=nil, delimiter=nil, http_conn=nil, full_listing=nil)
298
+ #todo: add in rest of functionality
299
+ if not http_conn
300
+ http_conn = http_connection(url)
301
+ end
302
+ parsed = http_conn[0].clone
303
+ conn = http_conn[1]
304
+
305
+ if full_listing
306
+ rv = get_account(url, token, marker, limit, prefix, http_conn)
307
+ listing = rv[1]
308
+ while listing.length > 0
309
+ marker = listing[-1]['name']
310
+ listing = get_account(url, token, marker, limit, prefix, http_conn)[1]
311
+ if listing.length > 0
312
+ rv[1] += listing
313
+ end
314
+ end
315
+ return rv
316
+ end
317
+ query = Query.new(parsed.query)
318
+ query.add('format', 'json')
319
+ query.add('marker', quote(marker.to_s)) if marker
320
+ query.add('limit', quote(limit.to_s)) if limit
321
+ query.add('prefix', quote(prefix.to_s)) if prefix
322
+ parsed.query = query.to_url_params
323
+ conn.start if !conn.started?
324
+ parsed.path += "/#{quote(container)}"
325
+ resp = conn.get(parsed.request_uri, {'x-auth-token' => token})
326
+ if resp.code.to_i < 200 or resp.code.to_i > 300
327
+ raise ClientException.new('Container GET failed', :http_scheme=>parsed.scheme,
328
+ :http_host=>conn.address, :http_port=>conn.port,
329
+ :http_path=>parsed.path, :http_query=>parsed.query, :http_status=>resp.code,
330
+ :http_reason=>resp.message)
331
+ end
332
+ resp_headers = {}
333
+ resp.header.each do |k,v|
334
+ resp_headers[k.downcase] = v
335
+ end
336
+ if resp.code.to_i == 204
337
+ [resp_headers, []]
338
+ else
339
+ [resp_headers, JSON.parse(resp.body())]
340
+ end
341
+ end
342
+
343
+ def get_container(container, marker=nil, limit=nil, prefix=nil, delimiter=nil, full_listing=nil)
344
+ _retry(nil, :get_container, [container, marker, limit, prefix, delimiter, full_listing])
345
+ end
346
+
347
+ def self.head_container(url, token, container, http_conn=nil)
348
+ if not http_conn
349
+ http_conn = http_connection(url)
350
+ end
351
+ parsed = http_conn[0].clone
352
+ conn = http_conn[1]
353
+
354
+ conn.start if !conn.started?
355
+ parsed.path += "/#{quote(container)}"
356
+ resp = conn.head(parsed.request_uri, {'x-auth-token' => token})
357
+ if resp.code.to_i < 200 or resp.code.to_i > 300
358
+ raise ClientException.new('Container HEAD failed', :http_scheme=>parsed.scheme,
359
+ :http_host=>conn.address, :http_port=>conn.port,
360
+ :http_path=>parsed.path, :http_status=>resp.code,
361
+ :http_reason=>resp.message)
362
+ end
363
+ resp_headers = {}
364
+ resp.header.each do |k,v|
365
+ resp_headers[k.downcase] = v
366
+ end
367
+ resp_headers
368
+ end
369
+
370
+ def head_container(container)
371
+ _retry(nil, :head_container, [container, @http_conn])
372
+ end
373
+
374
+ def self.put_container(url, token, container, headers={}, http_conn=nil)
375
+ if not http_conn
376
+ http_conn = http_connection(url)
377
+ end
378
+ parsed = http_conn[0].clone
379
+ conn = http_conn[1]
380
+
381
+ conn.start if !conn.started?
382
+ parsed.path += "/#{quote(container)}"
383
+ headers['x-auth-token'] = token
384
+ # headers['content-length'] = 0
385
+ resp = conn.put(parsed.request_uri, nil, headers)
386
+ if resp.code.to_i < 200 or resp.code.to_i > 300
387
+ raise ClientException.new('Container PUT failed', :http_scheme=>parsed.scheme,
388
+ :http_host=>conn.address, :http_port=>conn.port,
389
+ :http_path=>parsed.path, :http_status=>resp.code,
390
+ :http_reason=>resp.message)
391
+ end
392
+ end
393
+
394
+ def put_container(container, headers={})
395
+ _retry(nil, :put_container, [container, headers, @http_conn])
396
+ end
397
+
398
+ def self.post_container(url, token, container, headers={}, http_conn=nil)
399
+ if not http_conn
400
+ http_conn = http_connection(url)
401
+ end
402
+ parsed = http_conn[0].clone
403
+ conn = http_conn[1]
404
+
405
+ conn.start if !conn.started?
406
+ parsed.path += "/#{quote(container)}"
407
+ headers['x-auth-token'] = token
408
+ resp = conn.post(parsed.request_uri, nil, headers)
409
+ if resp.code.to_i < 200 or resp.code.to_i > 300
410
+ raise ClientException.new('Container POST failed', :http_scheme=>parsed.scheme,
411
+ :http_host=>conn.address, :http_port=>conn.port,
412
+ :http_path=>parsed.path, :http_status=>resp.code,
413
+ :http_reason=>resp.message)
414
+ end
415
+ end
416
+
417
+ def post_container(container, headers={})
418
+ _retry(nil, :post_container, [container, headers])
419
+ end
420
+
421
+ def self.delete_container(url, token, container, headers={}, http_conn=nil)
422
+ if not http_conn
423
+ http_conn = http_connection(url)
424
+ end
425
+ parsed = http_conn[0].clone
426
+ conn = http_conn[1]
427
+
428
+ conn.start if !conn.started?
429
+ parsed.path += "/#{quote(container)}"
430
+ headers['x-auth-token'] = token
431
+ resp = conn.delete(parsed.request_uri, headers)
432
+ if resp.code.to_i < 200 or resp.code.to_i > 300
433
+ raise ClientException.new('Container DELETE failed', :http_scheme=>parsed.scheme,
434
+ :http_host=>conn.address, :http_port=>conn.port,
435
+ :http_path=>parsed.path, :http_status=>resp.code,
436
+ :http_reason=>resp.message)
437
+ end
438
+ end
439
+
440
+ def delete_container(container)
441
+ _retry(nil, :delete_container, [container])
442
+ end
443
+
444
+ def self.get_object(url, token, container, name, http_conn=nil, resp_chunk_size=nil, &block)
445
+ if not http_conn
446
+ http_conn = http_connection(url)
447
+ end
448
+ parsed = http_conn[0].clone
449
+ conn = http_conn[1]
450
+
451
+
452
+ parsed.path += "/#{quote(container)}/#{quote(name)}"
453
+ conn.start if not conn.started?
454
+ headers = {'x-auth-token' => token}
455
+ if block_given?
456
+ resp = conn.request_get(parsed.request_uri, headers) do |r|
457
+ r.read_body do |b|
458
+ yield b
459
+ end
460
+ end
461
+ object_body = nil
462
+ else
463
+ resp = conn.request_get(parsed.request_uri, headers)
464
+ object_body = resp.body
465
+ end
466
+ if resp.code.to_i < 200 or resp.code.to_i > 300
467
+ raise ClientException.new('Object GET failed', :http_scheme=>parsed.scheme,
468
+ :http_host=>conn.address, :http_port=>conn.port,
469
+ :http_path=>parsed.path, :http_status=>resp.code,
470
+ :http_reason=>resp.message)
471
+ end
472
+ resp_headers = {}
473
+ resp.header.each do |k,v|
474
+ resp_headers[k.downcase] = v
475
+ end
476
+ [resp_headers, object_body]
477
+ end
478
+
479
+ def get_object(container, name, resp_chunk_size=nil)
480
+ _retry(nil, :get_object, [container, name, resp_chunk_size])
481
+ end
482
+
483
+ def self.head_object(url, token, container, name, http_conn=nil)
484
+ if not http_conn
485
+ http_conn = http_connection(url)
486
+ end
487
+ parsed = http_conn[0].clone
488
+ conn = http_conn[1]
489
+
490
+
491
+ parsed.path += "/#{quote(container)}/#{quote(name)}"
492
+ conn.start if not conn.started?
493
+ resp = conn.head(parsed.request_uri, {'x-auth-token' => token})
494
+ if resp.code.to_i < 200 or resp.code.to_i > 300
495
+ raise ClientException.new('Object HEAD failed', :http_scheme=>parsed.scheme,
496
+ :http_host=>conn.address, :http_port=>conn.port,
497
+ :http_path=>parsed.path, :http_status=>resp.code,
498
+ :http_reason=>resp.message)
499
+ end
500
+ resp_headers = {}
501
+ resp.header.each do |k,v|
502
+ resp_headers[k.downcase] = v
503
+ end
504
+ resp_headers
505
+ end
506
+
507
+ def head_object(container, name)
508
+ _retry(nil, :head_object, [container, name])
509
+ end
510
+
511
+ def self.put_object(url, token=nil, container=nil, name=nil, contents=nil,
512
+ content_length=nil, etag=nil, chunk_size=65536,
513
+ content_type=nil, headers={}, http_conn=nil, proxy=nil)
514
+ if not http_conn
515
+ http_conn = http_connection(url)
516
+ end
517
+ parsed = http_conn[0].clone
518
+ conn = http_conn[1]
519
+
520
+ parsed.path += "/#{quote(container)}" if container
521
+ parsed.path += "/#{quote(name)}" if name
522
+ headers['x-auth-token'] = token if token
523
+ headers['etag'] = etag if etag
524
+ if content_length != nil
525
+ headers['content-length'] = content_length.to_s
526
+ else
527
+ headers.each do |k,v|
528
+ if k.downcase == 'content-length'
529
+ content_length = v.to_i
530
+ end
531
+ end
532
+ end
533
+ headers['content-type'] = content_type if content_type
534
+ headers['content-length'] = '0' if not contents
535
+ if contents.respond_to? :read
536
+ request = Net::HTTP::Put.new(parsed.request_uri, headers)
537
+ chunked = ChunkedConnectionWrapper.new(contents, chunk_size)
538
+ if content_length == nil
539
+ request['Transfer-Encoding'] = 'chunked'
540
+ request.delete('content-length')
541
+ end
542
+ request.body_stream = chunked
543
+ resp = conn.start do |http|
544
+ http.request(request)
545
+ end
546
+ else
547
+ conn.start if not conn.started?
548
+ resp = conn.put(parsed.request_uri, contents, headers)
549
+ end
550
+ if resp.code.to_i < 200 or resp.code.to_i > 300
551
+ raise ClientException.new('Object PUT failed', :http_scheme=>parsed.scheme,
552
+ :http_host=>conn.address, :http_port=>conn.port,
553
+ :http_path=>parsed.path, :http_status=>resp.code,
554
+ :http_reason=>resp.message)
555
+ end
556
+ resp.header['etag']
557
+ end
558
+
559
+ def put_object(container, obj, contents, content_length=nil, etag=nil, chunk_size=65536, content_type=nil, headers={})
560
+
561
+ _default_reset = Proc.new do |args|
562
+ raise ClientException("put_object(#{container}, #{obj}, ...) failure and no ability to reset contents for reupload.")
563
+ end
564
+ reset_func = _default_reset
565
+ if (contents.respond_to? :seek) and (contents.respond_to? :tell)
566
+ orig_pos = contents.tell
567
+ reset_func = Proc.new {|a| contents.seek(orig_pos)}
568
+ elsif !contents
569
+ reset_func = Proc.new {|a| nil }
570
+ end
571
+ _retry(reset_func, :put_object, [container, obj, contents, content_length, etag, chunk_size, content_type, headers])
572
+ end
573
+
574
+ def self.post_object(url, token=nil, container=nil, name=nil, headers={}, http_conn=nil)
575
+ if not http_conn
576
+ http_conn = http_connection(url)
577
+ end
578
+ parsed = http_conn[0].clone
579
+ conn = http_conn[1]
580
+
581
+ parsed.path += "/#{quote(container)}" if container
582
+ parsed.path += "/#{quote(name)}" if name
583
+ headers['x-auth-token'] = token if token
584
+ resp = conn.post(parsed.request_uri, nil, headers)
585
+ if resp.code.to_i < 200 or resp.code.to_i > 300
586
+ raise ClientException.new('Object POST failed', :http_scheme=>parsed.scheme,
587
+ :http_host=>conn.address, :http_port=>conn.port,
588
+ :http_path=>parsed.path, :http_status=>resp.code,
589
+ :http_reason=>resp.message)
590
+ end
591
+ end
592
+
593
+ def post_object(container, name, headers={})
594
+ _retry(nil, :post_object, [container, name, headers])
595
+ end
596
+
597
+ def self.delete_object(url, token=nil, container=nil, name=nil, http_conn=nil, headers={}, proxy=nil)
598
+ if not http_conn
599
+ http_conn = http_connection(url)
600
+ end
601
+ parsed = http_conn[0].clone
602
+ conn = http_conn[1]
603
+
604
+ conn.start if !conn.started?
605
+ parsed.path += "/#{quote(container)}" if container
606
+ parsed.path += "/#{quote(name)}" if name
607
+ headers['x-auth-token'] = token if token
608
+ resp = conn.delete(parsed.request_uri, headers)
609
+ if resp.code.to_i < 200 or resp.code.to_i > 300
610
+ raise ClientException.new('Object DELETE failed', :http_scheme=>parsed.scheme,
611
+ :http_host=>conn.address, :http_port=>conn.port,
612
+ :http_path=>parsed.path, :http_status=>resp.code,
613
+ :http_reason=>resp.message)
614
+ end
615
+ end
616
+
617
+ def delete_object(container, name, headers={})
618
+ _retry(nil, :delete_object, [container, name, headers])
619
+ end
620
+ end