blobsterix 0.0.9

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 (67) hide show
  1. data/.gitignore +27 -0
  2. data/CHANGELOG.txt +13 -0
  3. data/Gemfile +16 -0
  4. data/LICENSE +22 -0
  5. data/README.md +122 -0
  6. data/Rakefile +13 -0
  7. data/bin/blobsterix +152 -0
  8. data/bin/test +26 -0
  9. data/blobsterix.gemspec +39 -0
  10. data/config/lighttpd.conf +50 -0
  11. data/lib/blobsterix.rb +213 -0
  12. data/lib/blobsterix/blob/blob_api.rb +55 -0
  13. data/lib/blobsterix/blob/blob_url_helper.rb +55 -0
  14. data/lib/blobsterix/helper/accept_type.rb +62 -0
  15. data/lib/blobsterix/helper/blob_access.rb +73 -0
  16. data/lib/blobsterix/helper/config_loader.rb +33 -0
  17. data/lib/blobsterix/helper/data_response.rb +54 -0
  18. data/lib/blobsterix/helper/http.rb +47 -0
  19. data/lib/blobsterix/helper/logable.rb +11 -0
  20. data/lib/blobsterix/helper/murmur.rb +137 -0
  21. data/lib/blobsterix/helper/status_info.rb +42 -0
  22. data/lib/blobsterix/helper/template_renderer.rb +39 -0
  23. data/lib/blobsterix/mimemagic/magic.rb +138 -0
  24. data/lib/blobsterix/mimemagic/tables.rb +1770 -0
  25. data/lib/blobsterix/mimemagic/version.rb +5 -0
  26. data/lib/blobsterix/router/app_router.rb +134 -0
  27. data/lib/blobsterix/s3/s3_api.rb +92 -0
  28. data/lib/blobsterix/s3/s3_url_helper.rb +93 -0
  29. data/lib/blobsterix/service.rb +34 -0
  30. data/lib/blobsterix/status/status_api.rb +62 -0
  31. data/lib/blobsterix/status/status_url_helper.rb +11 -0
  32. data/lib/blobsterix/storage/blob_meta_data.rb +60 -0
  33. data/lib/blobsterix/storage/bucket.rb +36 -0
  34. data/lib/blobsterix/storage/bucket_entry.rb +29 -0
  35. data/lib/blobsterix/storage/bucket_list.rb +26 -0
  36. data/lib/blobsterix/storage/cache.rb +90 -0
  37. data/lib/blobsterix/storage/file_system.rb +132 -0
  38. data/lib/blobsterix/storage/file_system_meta_data.rb +136 -0
  39. data/lib/blobsterix/storage/storage.rb +30 -0
  40. data/lib/blobsterix/transformation/image_transformation.rb +439 -0
  41. data/lib/blobsterix/transformation/transformation.rb +30 -0
  42. data/lib/blobsterix/transformation/transformation_chain.rb +78 -0
  43. data/lib/blobsterix/transformation/transformation_manager.rb +115 -0
  44. data/lib/blobsterix/version.rb +3 -0
  45. data/scripts/download.rb +30 -0
  46. data/scripts/test +6 -0
  47. data/spec/lib/blob/blob_api_spec.rb +81 -0
  48. data/spec/lib/helper/blob_access_spec.rb +72 -0
  49. data/spec/lib/s3/s3_api_spec.rb +183 -0
  50. data/spec/lib/service_spec.rb +12 -0
  51. data/spec/lib/status/status_api_spec.rb +42 -0
  52. data/spec/lib/storage/cache_spec.rb +135 -0
  53. data/spec/lib/storage/file_system_spec.rb +84 -0
  54. data/spec/spec_helper.rb +139 -0
  55. data/templates/app/Gemfile +12 -0
  56. data/templates/app/Rakefile +7 -0
  57. data/templates/app/config.rb +61 -0
  58. data/templates/app/config/environments/development.rb +40 -0
  59. data/templates/app/config/environments/production.rb +40 -0
  60. data/templates/app/storages/.keep +0 -0
  61. data/templates/app/transformators/.keep +0 -0
  62. data/templates/app/views/.keep +0 -0
  63. data/templates/storage_template.rb +30 -0
  64. data/templates/transformation_template.rb +41 -0
  65. data/templates/views/error_page.erb +18 -0
  66. data/templates/views/status_page.erb +31 -0
  67. metadata +325 -0
@@ -0,0 +1,30 @@
1
+ module Blobsterix::Transformations
2
+ class Transformation
3
+ include Blobsterix::Logable
4
+
5
+ def name
6
+ ""
7
+ end
8
+
9
+ def to_s
10
+ name
11
+ end
12
+
13
+ def is_format?
14
+ false
15
+ end
16
+
17
+ def input_type
18
+ Blobsterix::AcceptType.new
19
+ end
20
+
21
+ def output_type
22
+ Blobsterix::AcceptType.new
23
+ end
24
+
25
+ def transform(input_path, target_path, value)
26
+ logger.debug "run transformation!!!!!"
27
+ system("cp #{input_path} #{target_path}")
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,78 @@
1
+ module Blobsterix::Transformations
2
+ class TransformationChain
3
+ attr_reader :logger, :target_blob_access
4
+
5
+ def initialize(blob_access, input_data, logger)
6
+ @blob_access=blob_access
7
+ @target_blob_access=nil
8
+ @input_data = input_data
9
+ @transformations = []
10
+ @logger = logger
11
+ end
12
+
13
+ def cache
14
+ @cache||=Blobsterix.cache
15
+ end
16
+
17
+ def last_type()
18
+ return Blobsterix::AcceptType.new(@input_data.mimetype) if @transformations.empty?
19
+ @transformations.last[0].output_type
20
+ end
21
+
22
+ def add(transfo, value)
23
+ return if transfo == nil
24
+ @transformations << [transfo, value]
25
+ end
26
+
27
+ def do()
28
+
29
+ with_tempfiles do |keys|
30
+ last_key = "#{@input_data.path}"
31
+
32
+ begin
33
+ current_transformation = nil
34
+ @transformations.each{|trafo|
35
+
36
+ current_transformation = trafo
37
+
38
+ new_key = keys.delete_at(0)
39
+ trafo[0].transform(last_key, new_key, trafo[1])
40
+ last_key = new_key
41
+ }
42
+ rescue StandardError => e
43
+ logger.error "Transformation: #{current_transformation} failed with #{e.message}"
44
+ break
45
+ end
46
+
47
+ cache.put(@target_blob_access,Blobsterix::Storage::FileSystemMetaData.new(last_key).read)
48
+ @target_blob_access.reset!
49
+ end unless @target_blob_access.get.valid
50
+
51
+ @target_blob_access
52
+ end
53
+
54
+ def finish(accept_type, trafo)
55
+ if @transformations.empty? or (not @transformations.last[0].output_type.equal?(accept_type) and not @transformations.last[0].is_format?)
56
+ @transformations << [trafo, nil] if trafo != nil && trafo.is_format?
57
+ end
58
+ accept_type = @transformations.empty? || !@transformations.last[0].is_format? ? nil : @transformations.last[0].output_type
59
+ @target_blob_access = Blobsterix::BlobAccess.new(:bucket => @blob_access.bucket, :id => @blob_access.id, :trafo => @transformations.map{|trafo,value| [trafo.name, value]}, :accept_type => accept_type)
60
+ end
61
+
62
+ private
63
+
64
+ def with_tempfiles
65
+ tmpFiles = @transformations.size.times.map{|index|
66
+ Tempfile.new("#{@blob_access.identifier}_#{index}")
67
+ }
68
+ keys = tmpFiles.map{|f| f.path }
69
+
70
+ yield keys
71
+
72
+ tmpFiles.each { |f|
73
+ f.close
74
+ f.unlink
75
+ }
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,115 @@
1
+ module Blobsterix::Transformations
2
+ #a TransormationManager cares about:
3
+ class TransformationManager
4
+ include Blobsterix::Logable
5
+
6
+ def initialize()
7
+ auto_load
8
+ end
9
+
10
+ def add(trafo)
11
+ transformation = (trafo.is_a?(String) ? ::Blobsterix::Transformations::Impl::const_get(trafo).new : trafo)
12
+ transformations << transformation if transformations.select{|trafo|trafo.name === transformation.name}.empty?
13
+ self
14
+ end
15
+
16
+ def run(blob_access)
17
+
18
+ blob_access = wait_for_transformation(blob_access) if transformation_in_progress?(blob_access)
19
+
20
+ return blob_access.get if blob_access.get.valid
21
+
22
+ cue_transformation(blob_access)
23
+
24
+ blob_access = run_transformation(blob_access)
25
+
26
+ blob_access.get.valid ? blob_access.get : Blobsterix::Storage::BlobMetaData.new
27
+ end
28
+
29
+ private
30
+ def running_transformations
31
+ @running_transformations ||= {}
32
+ end
33
+
34
+ def transformations
35
+ @transformations ||= []
36
+ end
37
+
38
+ def wait_for_transformation(blob_access)
39
+ running_transformations[blob_access.identifier] << Fiber.current
40
+ logger.debug "Transformation: wait for it to finish #{blob_access}"
41
+ Fiber.yield
42
+ end
43
+
44
+ def cue_transformation(blob_access)
45
+ running_transformations[blob_access.identifier] = [Fiber.current]
46
+ blob_access
47
+ end
48
+
49
+ def uncue_transformation(blob_access)
50
+ running_transformations.delete(blob_access.identifier)
51
+ blob_access
52
+ end
53
+
54
+ def transformation_in_progress?(blob_access)
55
+ running = running_transformations.has_key?(blob_access.identifier)
56
+ running
57
+ end
58
+
59
+ def auto_load()
60
+ Blobsterix::Transformations::Impl.constants.each{|c|
61
+ add(c.to_s)
62
+ }
63
+ end
64
+
65
+ def run_transformation(blob_access)
66
+ logger.debug "Transformation: build #{blob_access}"
67
+
68
+ metaData = blob_access.source || Blobsterix::BlobAccess.new(:bucket => blob_access.bucket,:id => blob_access.id).get
69
+
70
+ return uncue_transformation(blob_access) unless metaData.valid
71
+
72
+ chain = TransformationChain.new(blob_access, metaData, logger)
73
+
74
+ blob_access.trafo.each {|trafo_pair|
75
+ chain.add(findTransformation(trafo_pair[0], chain.last_type), trafo_pair[1])
76
+ }
77
+
78
+ chain.finish(blob_access.accept_type, findTransformation_out(chain.last_type, blob_access.accept_type))
79
+
80
+ if chain.target_blob_access.get.valid
81
+ uncue_transformation(blob_access)
82
+ chain.target_blob_access
83
+ else
84
+ logger.debug "Transformation: run #{blob_access}"
85
+ EM.defer(Proc.new {
86
+ chain.do()
87
+ }, Proc.new {|result|
88
+ finish_connection(result, blob_access)
89
+ })
90
+
91
+ Fiber.yield
92
+ end
93
+ end
94
+
95
+ def finish_connection(result, blob_access)
96
+ logger.debug "Transformation: done #{blob_access} finish connections"
97
+ running_transformations[blob_access.identifier].each{|fiber|
98
+ fiber.resume(result)
99
+ }
100
+ uncue_transformation(blob_access)
101
+ end
102
+
103
+ def findTransformation(name, input_type)
104
+ trafos = transformations.select{|trafo| trafo.name === name and trafo.input_type.is?(input_type)}
105
+ trafos.empty? ? nil : trafos[0]
106
+ end
107
+
108
+ def findTransformation_out(input_type, output_type)
109
+ trafos = transformations.select{|trafo|
110
+ trafo.input_type.is?(input_type) and trafo.output_type.equal?(output_type)
111
+ }
112
+ trafos.empty? ? nil : trafos[0]
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,3 @@
1
+ module Blobsterix
2
+ VERSION = "0.0.9"
3
+ end
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'net/http'
4
+
5
+ uri = URI.parse("http://localhost:9000/blob/v1/rotate_25,ascii_250.images/expired.pngd")
6
+
7
+ # Net::HTTP.start("localhost", 9000) do |http|
8
+ # resp = http.get("/images/syncview21force.png")
9
+ # open("/home/dsudmann/desktop/syncview21force.png", "wb") do |file|
10
+ # file.write(resp.body)
11
+ # end
12
+ # end
13
+
14
+ # Net::HTTP.start(uri.host,uri.port) do |http|
15
+ # resp = http.get(uri.path)
16
+ # open("/home/dsudmann/desktop/syncview21force.png", "wb") do |file|
17
+ # file.write(resp.body)
18
+ # end
19
+ # end
20
+
21
+ Net::HTTP.start(uri.host,uri.port) do |http|
22
+ open("/home/dsudmann/desktop/syncview21force", "wb") do |file|
23
+ http.request_get(uri.path){ |resp|
24
+ puts resp.code
25
+ resp.read_body{ |seg|
26
+ file << seg
27
+ }
28
+ }
29
+ end
30
+ end
data/scripts/test ADDED
@@ -0,0 +1,6 @@
1
+ ab -n 100 -c 50 http://localhost:3000/blob/v1/rotate_10.images/expired.png > cache/log_00 &
2
+ ab -n 100 -c 50 http://localhost:3000/blob/v1/rotate_20.images/expired.png > cache/log_01 &
3
+ ab -n 100 -c 50 http://localhost:3000/blob/v1/rotate_30.images/expired.png > cache/log_02 &
4
+ ab -n 100 -c 50 http://localhost:3000/blob/v1/rotate_40.images/expired.png > cache/log_03 &
5
+ ab -n 100 -c 50 http://localhost:3000/blob/v1/rotate_50.images/expired.png > cache/log_04 &
6
+ ab -n 100 -c 50 http://localhost:3000/blob/v1/rotate_60.images/expired.png > cache/log_05 &
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+
3
+ describe Blobsterix::BlobApi do
4
+ include Rack::Test::Methods
5
+ def app
6
+ Blobsterix::BlobApi
7
+ end
8
+ describe 'GET /blob/v1/' do
9
+ it 'get several categories of repositories by name' do
10
+ get "/blob/v1/"
11
+ expect(last_response.status).to eql(403)
12
+ end
13
+ end
14
+
15
+ describe 'Transformed get' do
16
+ include Blobsterix::SpecHelper
17
+
18
+ context "with data" do
19
+ let(:data) {"Hi my name is Test"}
20
+ let(:data_transformed) {"Hi_my_name_is_Test_Transformed"}
21
+ let(:key) {"test.txt"}
22
+ let(:bucket) {"test"}
23
+
24
+ before :all do
25
+ Blobsterix.transformation.add Blobsterix::SpecHelper::DummyTrafo.new
26
+ end
27
+
28
+ after :all do
29
+ Blobsterix.transformation=Blobsterix::Transformations::TransformationManager.new
30
+ end
31
+
32
+ before :each do
33
+ Blobsterix.storage.put(bucket, key, StringIO.new(data, "r"))
34
+ end
35
+
36
+ after :each do
37
+ clear_data
38
+ end
39
+
40
+ it "should return the file" do
41
+ expect(Blobsterix.transformation).to receive(:cue_transformation).once.and_call_original
42
+ run_em do
43
+ get "/blob/v1/dummy_#{data_transformed}.test/test.txt"
44
+ end
45
+ expect(last_response.status).to eql(200)
46
+ expect(last_response.body).to eql(data_transformed)
47
+ end
48
+
49
+ it "should return the file head" do
50
+ expect(Blobsterix.transformation).to receive(:cue_transformation).once.and_call_original
51
+ run_em do
52
+ head "/blob/v1/dummy.test/test.txt"
53
+ end
54
+ expect(last_response.status).to eql(200)
55
+ expect(last_response.body).to eql("")
56
+ end
57
+
58
+ it "should return the file and wait for previous trafos to finish" do
59
+ expect(Blobsterix.transformation).to receive(:cue_transformation).once.and_call_original
60
+ expect(Blobsterix.transformation).to receive(:wait_for_transformation).once.and_call_original
61
+ run_em do
62
+ get "/blob/v1/dummy_#{data_transformed}.test/test.txt"
63
+ get "/blob/v1/dummy_#{data_transformed}.test/test.txt"
64
+ end
65
+ expect(last_response.status).to eql(200)
66
+ expect(last_response.body).to eql(data_transformed)
67
+ end
68
+
69
+ it "should return the file and not wait for different trafos to finish" do
70
+ expect(Blobsterix.transformation).to receive(:cue_transformation).twice.and_call_original
71
+ expect(Blobsterix.transformation).to receive(:wait_for_transformation).never.and_call_original
72
+ run_em do
73
+ get "/blob/v1/dummy_#{data_transformed},dummy_#{data_transformed}.test/test.txt"
74
+ get "/blob/v1/dummy_#{data_transformed}.test/test.txt"
75
+ end
76
+ expect(last_response.status).to eql(200)
77
+ expect(last_response.body).to eql(data_transformed)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,72 @@
1
+ require "spec_helper"
2
+
3
+ describe Blobsterix::BlobAccess do
4
+ include Blobsterix::SpecHelper
5
+
6
+ let(:data) {"Hi my name is Test"}
7
+ let(:key) {"test.txt"}
8
+ let(:bucket) {"test"}
9
+
10
+ def blob_access
11
+ Blobsterix::BlobAccess.new(:bucket => bucket, :id => key)
12
+ end
13
+ def blob_access_1
14
+ Blobsterix::BlobAccess.new(:bucket => bucket, :id => key, :trafo => [["test", ""]])
15
+ end
16
+ def blob_access_raw
17
+ Blobsterix::BlobAccess.new(:bucket => bucket, :id => key, :trafo => [["raw", ""]])
18
+ end
19
+ def blob_access_same_accept_type
20
+ Blobsterix::BlobAccess.new(:bucket => bucket, :id => key, :accept_type => Blobsterix::AcceptType.new("text/plain"))
21
+ end
22
+ def blob_access_raw_same_accept_type
23
+ Blobsterix::BlobAccess.new(:bucket => bucket, :id => key, :trafo => [["raw", ""]], :accept_type => Blobsterix::AcceptType.new("text/plain"))
24
+ end
25
+
26
+ describe "blob_access" do
27
+ after :each do
28
+ clear_data
29
+ end
30
+
31
+ it "should return valid blob data when it exists" do
32
+ Blobsterix.storage.put(bucket, key, StringIO.new(data, "r"))
33
+ expect(blob_access.get().valid).to be(true)
34
+ end
35
+
36
+ it "should return invalid blob data when it does not exist" do
37
+ expect(blob_access.get().valid).to be(false)
38
+ end
39
+
40
+ it "should automaticly guess raw trafo" do
41
+ Blobsterix.storage.put(bucket, key, StringIO.new(data, "r"))
42
+ expect(blob_access.get().valid).to be(true)
43
+ expect(blob_access_raw.get().valid).to be(true)
44
+ expect(blob_access_same_accept_type.get().valid).to be(true)
45
+ expect(blob_access_raw_same_accept_type.get().valid).to be(true)
46
+ end
47
+
48
+ context "dont cache raw" do
49
+ before :each do
50
+ Blobsterix.cache_original= false
51
+ end
52
+
53
+ it "should not create a cache entry for raw transforms" do
54
+ Blobsterix.storage.put(bucket, key, StringIO.new(data, "r"))
55
+ expect(blob_access.get().valid).to be(true)
56
+ expect(Blobsterix.cache.get(blob_access).valid).to be(false)
57
+ end
58
+ end
59
+
60
+ context "cache raw" do
61
+ before :each do
62
+ Blobsterix.cache_original= true
63
+ end
64
+
65
+ it "should create a cache entry for raw transforms" do
66
+ Blobsterix.storage.put(bucket, key, StringIO.new(data, "r"))
67
+ expect(blob_access.get().valid).to be(true)
68
+ expect(Blobsterix.cache.get(blob_access).valid).to be(true)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,183 @@
1
+ require "spec_helper"
2
+
3
+ describe Blobsterix::S3Api do
4
+ include Rack::Test::Methods
5
+ include Blobsterix::SpecHelper
6
+ def app
7
+ Blobsterix::S3Api
8
+ end
9
+
10
+ let(:data) {"Hi my name is Test"}
11
+ let(:key) {"test.txt"}
12
+ let(:bucket) {"test"}
13
+
14
+ after :each do
15
+ clear_data
16
+ end
17
+
18
+ describe "create a bucket" do
19
+ it "should have bucket after creation" do
20
+
21
+ run_em do
22
+ put "/", "", "HTTP_HOST" => "#{bucket}.s3.blah.de"
23
+ end
24
+
25
+ get "/#{bucket}"
26
+ expect(last_response.status).to eql(200)
27
+ response = Hash.from_xml last_response.body
28
+ expect(response).to_not have_key(:Error)
29
+ end
30
+ end
31
+
32
+ describe "upload" do
33
+
34
+ before :all do
35
+ Blobsterix.transformation.add Blobsterix::SpecHelper::DummyTrafo.new
36
+ end
37
+
38
+ after :all do
39
+ Blobsterix.transformation=Blobsterix::Transformations::TransformationManager.new
40
+ end
41
+
42
+ after :each do
43
+ clear_data
44
+ end
45
+
46
+ it "should have file in bucket after upload" do
47
+ #expect(Blobsterix.transformation).to receive(:cue_transformation).never.and_call_original
48
+
49
+ run_em do
50
+ put "/#{key}", data, {"HTTP_HOST" => "#{bucket}.s3.blah.de"}
51
+ end
52
+
53
+ expect(last_response.status).to eql(200)
54
+ expect(Blobsterix.storage.get(bucket, key).read).to eql(data)
55
+ end
56
+
57
+ it "should have file in bucket after upload with trafo" do
58
+ #expect(Blobsterix.transformation).to receive(:cue_transformation).once.and_call_original
59
+
60
+ run_em do
61
+ put "/#{key}", data, {"HTTP_HOST" => "#{bucket}.s3.blah.de", "HTTP_X_AMZ_META_TRAFO" => "dummy_Yeah"}
62
+ end
63
+
64
+ expect(last_response.status).to eql(200)
65
+ expect(Blobsterix.storage.get(bucket, key).read).to eql("Yeah")
66
+ end
67
+ end
68
+
69
+ context "with no data" do
70
+
71
+ describe "bucket" do
72
+ it 'should return an empty set' do
73
+ get "/"
74
+ expect(last_response.status).to eql(200)
75
+ response = Hash.from_xml last_response.body
76
+ expect(response).to have_key(:ListAllMyBucketsResult)
77
+ expect(response[:ListAllMyBucketsResult]).to have_key(:Buckets)
78
+ expect(response[:ListAllMyBucketsResult][:Buckets]).to be_empty
79
+ end
80
+
81
+ it 'should say no such bucket' do
82
+ get "/#{bucket}"
83
+ expect(last_response.status).to eql(200)
84
+ response = Hash.from_xml last_response.body
85
+ expect(response).to have_key(:Error)
86
+ expect(response[:Error]).to eql("no such bucket")
87
+ end
88
+
89
+ it "should return 404 on delete bucket" do
90
+ expect(Blobsterix.storage.bucket_exist(bucket)).to eql(false)
91
+
92
+ delete "/", "", "HTTP_HOST" => "s3.blah.de"
93
+
94
+ expect(last_response.status).to eql(404)
95
+ expect(Blobsterix.storage.bucket_exist(bucket)).to eql(false)
96
+ end
97
+ end
98
+
99
+ describe 'file' do
100
+ it "should return a 404 when bucket doesn't exist" do
101
+ get "/#{key}", "", "HTTP_HOST" => "#{bucket}.s3.blah.de"
102
+ expect(last_response.status).to eql(404)
103
+ end
104
+
105
+ it 'should return a 404 when bucket exists' do
106
+ Blobsterix.storage.create(bucket)
107
+ get "/#{key}", "", "HTTP_HOST" => "#{bucket}.s3.blah.de"
108
+ expect(last_response.status).to eql(404)
109
+ Blobsterix.storage.delete(bucket)
110
+ end
111
+ end
112
+ end
113
+
114
+ context "with data" do
115
+
116
+ before :each do
117
+ Blobsterix.storage.put(bucket, key, StringIO.new(data, "r"))
118
+ end
119
+
120
+ after :each do
121
+ clear_storage
122
+ end
123
+
124
+ describe "bucket" do
125
+
126
+ it 'should return one bucket in the list' do
127
+ get "/"
128
+ expect(last_response.status).to eql(200)
129
+ response = Hash.from_xml last_response.body
130
+ expect(response).to have_key(:ListAllMyBucketsResult)
131
+ expect(response[:ListAllMyBucketsResult]).to have_key(:Buckets)
132
+ expect(response[:ListAllMyBucketsResult][:Buckets]).to_not be_empty
133
+ end
134
+
135
+ it 'should return all files for the bucket' do
136
+ get "/#{bucket}"
137
+ expect(last_response.status).to eql(200)
138
+ response = Hash.from_xml last_response.body
139
+ expect(response).to have_key(:ListBucketResult)
140
+ expect(response[:ListBucketResult]).to have_key(:Name)
141
+ expect(response[:ListBucketResult][:Name]).to eql(bucket)
142
+ expect(response[:ListBucketResult][:Contents]).to_not be_empty
143
+ expect(response[:ListBucketResult][:Contents][:Key]).to eql(key)
144
+ expect(response[:ListBucketResult][:Contents][:MimeType]).to eql("text/plain")
145
+ expect(response[:ListBucketResult][:Contents][:Size]).to eql(data.length)
146
+ expect(response[:ListBucketResult][:Contents][:ETag]).to eql(Digest::MD5.hexdigest(data))
147
+ end
148
+
149
+ it "should delete bucket" do
150
+ Blobsterix.storage.delete_key(bucket, key)
151
+ expect(Blobsterix.storage.bucket_exist(bucket)).to eql(true)
152
+
153
+ delete "/", "", "HTTP_HOST" => "#{bucket}.s3.blah.de"
154
+
155
+ expect(last_response.status).to eql(204)
156
+ expect(Blobsterix.storage.bucket_exist(bucket)).to eql(false)
157
+ end
158
+
159
+ end
160
+
161
+ describe "file" do
162
+
163
+ it "should return file" do
164
+ get "/#{key}", "", "HTTP_HOST" => "#{bucket}.s3.blah.de"
165
+ expect(last_response.status).to eql(200)
166
+ expect(last_response.body).to eql(data)
167
+ end
168
+
169
+ it "should return file head" do
170
+ head "/#{key}", "", "HTTP_HOST" => "#{bucket}.s3.blah.de"
171
+ expect(last_response.status).to eql(200)
172
+ expect(last_response.body).to eql("")
173
+ end
174
+
175
+ it "should delete key" do
176
+ delete "/#{key}", "", "HTTP_HOST" => "#{bucket}.s3.blah.de"
177
+
178
+ expect(last_response.status).to eql(204)
179
+ expect(Blobsterix.storage.get(bucket, key).valid).to eql(false)
180
+ end
181
+ end
182
+ end
183
+ end