httpimagestore 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/Gemfile +10 -12
  2. data/Gemfile.lock +57 -55
  3. data/README.md +829 -0
  4. data/VERSION +1 -1
  5. data/bin/httpimagestore +114 -180
  6. data/features/cache-control.feature +26 -90
  7. data/features/compatibility.feature +129 -0
  8. data/features/error-reporting.feature +207 -0
  9. data/features/health-check.feature +30 -0
  10. data/features/s3-store-and-thumbnail.feature +65 -0
  11. data/features/step_definitions/httpimagestore_steps.rb +66 -26
  12. data/features/support/env.rb +32 -5
  13. data/features/support/test.empty +0 -0
  14. data/httpimagestore.gemspec +60 -47
  15. data/lib/httpimagestore/aws_sdk_regions_hack.rb +23 -0
  16. data/lib/httpimagestore/configuration/file.rb +120 -0
  17. data/lib/httpimagestore/configuration/handler.rb +239 -0
  18. data/lib/httpimagestore/configuration/output.rb +119 -0
  19. data/lib/httpimagestore/configuration/path.rb +77 -0
  20. data/lib/httpimagestore/configuration/s3.rb +194 -0
  21. data/lib/httpimagestore/configuration/thumbnailer.rb +244 -0
  22. data/lib/httpimagestore/configuration.rb +126 -29
  23. data/lib/httpimagestore/error_reporter.rb +36 -0
  24. data/lib/httpimagestore/ruby_string_template.rb +26 -0
  25. data/load_test/load_test.1k.23a022f6e.m1.small-comp.csv +3 -0
  26. data/load_test/load_test.1k.ec9bde794.m1.small.csv +4 -0
  27. data/load_test/load_test.jmx +344 -0
  28. data/load_test/thumbnail_specs.csv +11 -0
  29. data/spec/configuration_file_spec.rb +309 -0
  30. data/spec/configuration_handler_spec.rb +124 -0
  31. data/spec/configuration_output_spec.rb +338 -0
  32. data/spec/configuration_path_spec.rb +92 -0
  33. data/spec/configuration_s3_spec.rb +571 -0
  34. data/spec/configuration_spec.rb +80 -105
  35. data/spec/configuration_thumbnailer_spec.rb +417 -0
  36. data/spec/ruby_string_template_spec.rb +43 -0
  37. data/spec/spec_helper.rb +61 -0
  38. data/spec/support/compute.jpg +0 -0
  39. data/spec/support/cuba_response_env.rb +40 -0
  40. data/spec/support/full.cfg +49 -0
  41. metadata +138 -84
  42. data/README.rdoc +0 -23
  43. data/features/httpimagestore.feature +0 -167
  44. data/lib/httpimagestore/image_path.rb +0 -54
  45. data/lib/httpimagestore/s3_service.rb +0 -37
  46. data/lib/httpimagestore/thumbnail_class.rb +0 -13
  47. data/spec/image_path_spec.rb +0 -72
  48. data/spec/test.cfg +0 -8
@@ -0,0 +1,207 @@
1
+ Feature: Image list based thumbnailing and S3 storage
2
+ Storage based on URL specified image names to be generated and stored using two different path formats.
3
+ This configuration should be mostly compatible with pre v1.0 release.
4
+
5
+ Background:
6
+ Given S3 settings in AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_S3_TEST_BUCKET environment variables
7
+ Given httpimagestore server is running at http://localhost:3000/ with the following configuration
8
+ """
9
+ s3 key="@AWS_ACCESS_KEY_ID@" secret="@AWS_SECRET_ACCESS_KEY@" ssl=false
10
+
11
+ path "structured-name" "#{dirname}/#{digest}/#{basename}-#{imagename}.#{mimeextension}"
12
+ path "missing" "blah"
13
+ path "zero" "zero"
14
+
15
+ put "multipart" ":name_list" {
16
+ thumbnail "input" {
17
+ "small" operation="crop" width=128 height=128 if-image-name-on="#{name_list}"
18
+ "bad" operation="crop" width=0 height=0 if-image-name-on="#{name_list}"
19
+ "bad_dim" operation="crop" width="128x" height=128 if-image-name-on="#{name_list}"
20
+ "superlarge" operation="crop" width=16000 height=16000 if-image-name-on="#{name_list}"
21
+ "large_png" operation="crop" width=7000 height=7000 format="png" if-image-name-on="#{name_list}"
22
+ "bad_opts" operation="crop" width=128 height=128 options="foo=bar" if-image-name-on="#{name_list}"
23
+ }
24
+ }
25
+
26
+ put "singlepart" ":name_list" {
27
+ thumbnail "input" "small" operation="crop" width=128 height=128 if-image-name-on="#{name_list}"
28
+ thumbnail "input" "bad" operation="crop" width=0 height=0 if-image-name-on="#{name_list}"
29
+ thumbnail "input" "bad_dim" operation="crop" width="128x" height=128 if-image-name-on="#{name_list}"
30
+ thumbnail "input" "superlarge" operation="crop" width=16000 height=16000 if-image-name-on="#{name_list}"
31
+ thumbnail "input" "large_png" operation="crop" width=7000 height=7000 format="png" if-image-name-on="#{name_list}"
32
+ thumbnail "input" "bad_opts" operation="crop" width=128 height=128 options="foo=bar" if-image-name-on="#{name_list}"
33
+ }
34
+
35
+ get "s3" {
36
+ source_s3 "original" bucket="@AWS_S3_TEST_BUCKET@" path="missing"
37
+ }
38
+
39
+ get "file" {
40
+ source_file "original" root="/tmp" path="missing"
41
+ }
42
+
43
+ get "zero" {
44
+ source_file "original" root="/dev" path="zero"
45
+ }
46
+ """
47
+ Given httpthumbnailer server is running at http://localhost:3100/
48
+
49
+ @error-reporting
50
+ Scenario: Reporting of missing resource
51
+ When I do GET request http://localhost:3000/blah
52
+ Then response status will be 404
53
+ And response content type will be text/plain
54
+ And response body will be CRLF ended lines
55
+ """
56
+ request for URI '/blah' was not handled by the server
57
+ """
58
+
59
+ @error-reporting
60
+ Scenario: Reporting of missing S3 resource
61
+ When I do GET request http://localhost:3000/s3
62
+ Then response status will be 404
63
+ And response content type will be text/plain
64
+ And response body will be CRLF ended lines
65
+ """
66
+ S3 bucket 'httpimagestoretest' does not contain key 'blah'
67
+ """
68
+
69
+ @error-reporting
70
+ Scenario: Reporting of missing file resource
71
+ When I do GET request http://localhost:3000/file
72
+ Then response status will be 404
73
+ And response content type will be text/plain
74
+ And response body will be CRLF ended lines
75
+ """
76
+ error while processing image 'original': file 'blah' not found
77
+ """
78
+
79
+ @error-reporting
80
+ Scenario: Reporting of unsupported media type
81
+ Given test.txt file content as request body
82
+ When I do PUT request http://localhost:3000/multipart/small,tiny
83
+ Then response status will be 415
84
+ And response content type will be text/plain
85
+ And response body will be CRLF ended lines like
86
+ """
87
+ thumbnailing of 'input' failed: unsupported media type: no decode delegate for this image format
88
+ """
89
+ When I do PUT request http://localhost:3000/singlepart/small,tiny
90
+ Then response status will be 415
91
+ And response content type will be text/plain
92
+ And response body will be CRLF ended lines like
93
+ """
94
+ thumbnailing of 'input' into 'small' failed: unsupported media type: no decode delegate for this image format
95
+ """
96
+
97
+ @error-reporting
98
+ Scenario: Reporting and handling of thumbnailing errors
99
+ Given test.jpg file content as request body
100
+ When I do PUT request http://localhost:3000/multipart/small,bad
101
+ Then response status will be 400
102
+ And response content type will be text/plain
103
+ And response body will be CRLF ended lines like
104
+ """
105
+ thumbnailing of 'input' into 'bad' failed: at least one image dimension is zero: 0x0
106
+ """
107
+ When I do PUT request http://localhost:3000/singlepart/small,bad
108
+ Then response status will be 400
109
+ And response content type will be text/plain
110
+ And response body will be CRLF ended lines like
111
+ """
112
+ thumbnailing of 'input' into 'bad' failed: at least one image dimension is zero: 0x0
113
+ """
114
+
115
+ @error-reporting
116
+ Scenario: Reporting and handling of thumbnailing errors - bad options format
117
+ Given test.jpg file content as request body
118
+ When I do PUT request http://localhost:3000/multipart/small,bad_opts
119
+ Then response status will be 400
120
+ And response content type will be text/plain
121
+ And response body will be CRLF ended lines
122
+ """
123
+ thumbnailing of 'input' into 'bad_opts' failed: missing option value for key 'foo=bar'
124
+ """
125
+ When I do PUT request http://localhost:3000/singlepart/small,bad_opts
126
+ Then response status will be 400
127
+ And response content type will be text/plain
128
+ And response body will be CRLF ended lines
129
+ """
130
+ thumbnailing of 'input' into 'bad_opts' failed: missing option value for key 'foo=bar'
131
+ """
132
+
133
+ @error-reporting @test
134
+ Scenario: Bad dimension
135
+ Given test.jpg file content as request body
136
+ When I do PUT request http://localhost:3000/multipart/bad_dim
137
+ Then response status will be 400
138
+ And response content type will be text/plain
139
+ And response body will be CRLF ended lines like
140
+ """
141
+ thumbnailing of 'input' into 'bad_dim' failed: bad dimension value: 128x
142
+ """
143
+ When I do PUT request http://localhost:3000/singlepart/bad_dim
144
+ Then response status will be 400
145
+ And response content type will be text/plain
146
+ And response body will be CRLF ended lines like
147
+ """
148
+ thumbnailing of 'input' into 'bad_dim' failed: bad dimension value: 128x
149
+ """
150
+
151
+ @error-reporting
152
+ Scenario: Too large image - uploaded image too big to fit in memory limit
153
+ Given test-large.jpg file content as request body
154
+ When I do PUT request http://localhost:3000/multipart/large_png
155
+ Then response status will be 413
156
+ And response content type will be text/plain
157
+ And response body will be CRLF ended lines like
158
+ """
159
+ thumbnailing of 'input' failed: image too large: cache resources exhausted
160
+ """
161
+ When I do PUT request http://localhost:3000/singlepart/large_png
162
+ Then response status will be 413
163
+ And response content type will be text/plain
164
+ And response body will be CRLF ended lines like
165
+ """
166
+ thumbnailing of 'input' into 'large_png' failed: image too large: cache resources exhausted
167
+ """
168
+
169
+ @error-reporting
170
+ Scenario: Too large image - memory exhausted when thmbnailing
171
+ Given test.jpg file content as request body
172
+ When I do PUT request http://localhost:3000/multipart/superlarge
173
+ Then response status will be 413
174
+ And response content type will be text/plain
175
+ And response body will be CRLF ended lines like
176
+ """
177
+ thumbnailing of 'input' into 'superlarge' failed: image too large: cache resources exhausted
178
+ """
179
+ When I do PUT request http://localhost:3000/singlepart/superlarge
180
+ Then response status will be 413
181
+ And response content type will be text/plain
182
+ And response body will be CRLF ended lines like
183
+ """
184
+ thumbnailing of 'input' into 'superlarge' failed: image too large: cache resources exhausted
185
+ """
186
+
187
+ @error-reporting
188
+ Scenario: Zero body length
189
+ Given test.empty file content as request body
190
+ When I do PUT request http://localhost:3000/multipart/small
191
+ Then response status will be 400
192
+ And response content type will be text/plain
193
+ And response body will be CRLF ended lines like
194
+ """
195
+ empty body - expected image data
196
+ """
197
+
198
+ @error-reporting
199
+ Scenario: Memory limit exceeded
200
+ When I do GET request http://localhost:3000/zero
201
+ Then response status will be 413
202
+ And response content type will be text/plain
203
+ And response body will be CRLF ended lines like
204
+ """
205
+ memory limit exceeded
206
+ """
207
+
@@ -0,0 +1,30 @@
1
+ Feature: Health check URL
2
+ Server can be tested with GET request to '/health_check'.
3
+
4
+ Background:
5
+ Given httpimagestore server is running at http://localhost:3000/ with the following configuration
6
+ """
7
+ """
8
+
9
+ @health-check
10
+ Scenario: Passing health check when thumbnailer is running
11
+ Given httpthumbnailer server is running at http://localhost:3100/
12
+ When I do GET request http://localhost:3000/health_check
13
+ Then response status will be 200
14
+ And response content type will be text/plain
15
+ And response body will be CRLF ended lines
16
+ """
17
+ HTTP Image Store OK
18
+ """
19
+
20
+ @health-check
21
+ Scenario: Failing health check when thumbnailer is not running
22
+ Given httpthumbnailer server is not running
23
+ When I do GET request http://localhost:3000/health_check
24
+ Then response status will be 502
25
+ And response content type will be text/plain
26
+ And response body will be CRLF ended lines
27
+ """
28
+ Connection refused - connect(2) (http://localhost:3100)
29
+ """
30
+
@@ -0,0 +1,65 @@
1
+ Feature: Store limited original image in S3 and thumbnail based on request
2
+ Posted image will be converted to JPEG and resized if it is bigger that given dimensions.
3
+ Than it will get stored on S3.
4
+ Get interface will allow to fetch the image from S3 and thumbnailing to given parameters.
5
+
6
+ Background:
7
+ Given S3 settings in AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_S3_TEST_BUCKET environment variables
8
+ Given httpimagestore server is running at http://localhost:3000/ with the following configuration
9
+ """
10
+ s3 key="@AWS_ACCESS_KEY_ID@" secret="@AWS_SECRET_ACCESS_KEY@" ssl=false
11
+
12
+ path "original-hash" "#{digest}.#{mimeextension}"
13
+ path "path" "#{path}"
14
+
15
+ put "original" {
16
+ thumbnail "input" "original" operation="limit" width=100 height=100 format="jpeg" quality=95
17
+
18
+ store_s3 "original" bucket="@AWS_S3_TEST_BUCKET@" path="original-hash"
19
+
20
+ output_store_path "original"
21
+ }
22
+
23
+ get "thumbnail" "v1" ":path" ":operation" ":width" ":height" ":options?" {
24
+ source_s3 "original" bucket="@AWS_S3_TEST_BUCKET@" path="path"
25
+
26
+ thumbnail "original" "thumbnail" operation="#{operation}" width="#{width}" height="#{height}" options="#{options}" quality=84 format="png"
27
+
28
+ output_image "thumbnail" cache-control="public, max-age=31557600, s-maxage=0"
29
+ }
30
+
31
+ """
32
+ Given httpthumbnailer server is running at http://localhost:3100/
33
+
34
+ @s3-store-and-thumbnail
35
+ Scenario: Putting original to S3 bucket
36
+ Given there is no 4006450256177f4a.jpg file in S3 bucket
37
+ Given test.jpg file content as request body
38
+ When I do PUT request http://localhost:3000/original
39
+ Then response status will be 200
40
+ And response content type will be text/plain
41
+ And response body will be CRLF ended lines
42
+ """
43
+ 4006450256177f4a.jpg
44
+ """
45
+ Then S3 object 4006450256177f4a.jpg will contain JPEG image of size 71x100
46
+ When I do GET request http://@AWS_S3_TEST_BUCKET@.s3.amazonaws.com/4006450256177f4a.jpg
47
+ Then response status will be 403
48
+
49
+ @s3-store-and-thumbnail
50
+ Scenario: Getting thumbnail to spec based on uploaded S3 image
51
+ Given test.jpg file content is stored in S3 under 4006450256177f4a.jpg
52
+ When I do GET request http://localhost:3000/thumbnail/v1/4006450256177f4a.jpg/pad/50/50
53
+ Then response status will be 200
54
+ And response content type will be image/png
55
+ Then response body will contain PNG image of size 50x50
56
+
57
+ @s3-store-and-thumbnail
58
+ Scenario: Getting thumbnail to spec based on uploaded S3 image - with options passed
59
+ Given test.jpg file content is stored in S3 under 4006450256177f4a.jpg
60
+ When I do GET request http://localhost:3000/thumbnail/v1/4006450256177f4a.jpg/pad/50/50/background-color:green
61
+ Then response status will be 200
62
+ And response content type will be image/png
63
+ Then response body will contain PNG image of size 50x50
64
+ And that image pixel at 2x2 should be of color green
65
+
@@ -3,15 +3,19 @@ Given /httpimagestore argument (.*)/ do |arg|
3
3
  end
4
4
 
5
5
  Given /httpimagestore server is running at (.*) with the following configuration/ do |url, config|
6
- cfile = Tempfile.new('httpimagestore.conf')
7
- cfile.write(config)
8
- cfile.close
6
+ $temp_dir = Pathname.new(Dir.mktmpdir) unless $temp_dir
7
+
8
+ cfile = $temp_dir + Digest.hexencode(Digest::MD5.digest(config))
9
+ cfile.open('w') do |io|
10
+ io.write(config.replace_s3_variables)
11
+ end
9
12
 
10
13
  begin
14
+ log = support_dir + 'server.log'
11
15
  start_server(
12
- "bundle exec #{script('httpimagestore')} #{(@httpimagestore_args ||= []).join(' ')} #{cfile.path}",
16
+ "bundle exec #{script('httpimagestore')} -f -d -l #{log} -w 1 #{(@httpimagestore_args ||= []).join(' ')} #{cfile.to_s}",
13
17
  '/tmp/httpimagestore.pid',
14
- support_dir + 'server.log',
18
+ log,
15
19
  url
16
20
  )
17
21
  ensure
@@ -20,14 +24,19 @@ Given /httpimagestore server is running at (.*) with the following configuration
20
24
  end
21
25
 
22
26
  Given /httpthumbnailer server is running at (.*)/ do |url|
27
+ log = support_dir + 'thumbniler.log'
23
28
  start_server(
24
- "httpthumbnailer",
29
+ "httpthumbnailer -f -d -l #{log} -w 1",
25
30
  '/tmp/httpthumbnailer.pid',
26
- support_dir + 'thumbniler.log',
31
+ log,
27
32
  url
28
33
  )
29
34
  end
30
35
 
36
+ Given /httpthumbnailer server is not running/ do
37
+ stop_server('/tmp/httpthumbnailer.pid')
38
+ end
39
+
31
40
  Given /httpimagestore log is empty/ do
32
41
  log = support_dir + 'server.log'
33
42
  log.truncate(0) if log.exist?
@@ -38,16 +47,21 @@ Given /httpthumbnailer log is empty/ do
38
47
  log.truncate(0) if log.exist?
39
48
  end
40
49
 
41
- Given /(.*) file content as request body/ do |file|
50
+ Given /^([^ ]*) file content as request body/ do |file|
42
51
  @request_body = File.open(support_dir + file){|f| f.read }
43
52
  end
44
53
 
45
- Given /(.*) S3 bucket with key (.*) and secret (.*)/ do |bucket, key_id, key_secret|
46
- @bucket = S3::Service.new(:access_key_id => key_id, :secret_access_key => key_secret).buckets.find(bucket)
54
+ Given /S3 settings in AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_S3_TEST_BUCKET environment variables/ do
55
+
56
+ unless ENV['AWS_ACCESS_KEY_ID'] and ENV['AWS_SECRET_ACCESS_KEY'] and ENV['AWS_S3_TEST_BUCKET']
57
+ fail "AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY or AWS_S3_TEST_BUCKET environment variables not set"
58
+ end
59
+
60
+ @bucket = AWS::S3.new(access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], use_ssl: false).buckets[ENV['AWS_S3_TEST_BUCKET']]
47
61
  end
48
62
 
49
63
  Given /there is no (.*) file in S3 bucket/ do |path|
50
- @bucket.objects.find(path).destroy rescue S3::Error::NoSuchKey
64
+ @bucket.objects[path].delete # rescue S3::Error::NoSuchKey
51
65
  end
52
66
 
53
67
  Given /(.*) header set to (.*)/ do |header, value|
@@ -55,8 +69,16 @@ Given /(.*) header set to (.*)/ do |header, value|
55
69
  @request_headers[header] = value
56
70
  end
57
71
 
72
+ Given /(.*) file content is stored in S3 under (.*)/ do |file, key|
73
+ @bucket.objects[key].write(File.open(support_dir + file){|f| f.read }, content_type: 'image/jpeg')
74
+ end
75
+
76
+ Then /S3 bucket will not contain (.*)/ do |key|
77
+ @bucket.objects[key].exists?.should_not be_true
78
+ end
79
+
58
80
  When /I do (.*) request (.*)/ do |method, uri|
59
- @response = HTTPClient.new.request(method, URI.encode(uri), nil, @request_body, (@request_headers or {}))
81
+ @response = HTTPClient.new.request(method, URI.encode(uri.replace_s3_variables), nil, @request_body, (@request_headers or {}))
60
82
  end
61
83
 
62
84
  Then /response status will be (.*)/ do |status|
@@ -68,30 +90,30 @@ Then /response content type will be (.*)/ do |content_type|
68
90
  end
69
91
 
70
92
  Then /response body will be CRLF ended lines like/ do |body|
71
- @response.body.should match(body)
93
+ @response.body.should match(body.replace_s3_variables)
72
94
  @response.body.each_line do |line|
73
95
  line[-2,2].should == "\r\n"
74
96
  end
75
97
  end
76
98
 
77
99
  Then /response body will be CRLF ended lines$/ do |body|
78
- @response.body.should == body.gsub("\n", "\r\n") + "\r\n"
100
+ @response.body.should == body.replace_s3_variables.gsub("\n", "\r\n") + "\r\n"
79
101
  end
80
102
 
81
103
  Then /(http.*) content type will be (.*)/ do |url, content_type|
82
- get_headers(url)['Content-Type'].should == content_type
104
+ get_headers(url.replace_s3_variables)['Content-Type'].should == content_type
83
105
  end
84
106
 
85
107
  Then /(http.*) ([^ ]+) header will be (.*)/ do |url, header, value|
86
- get_headers(url)[header].should == value
108
+ get_headers(url.replace_s3_variables)[header].should == value
87
109
  end
88
110
 
89
111
  Then /(http.*) ([^ ]+) header will not be set/ do |url, header|
90
- get_headers(url)[header].should be_nil
112
+ get_headers(url.replace_s3_variables)[header].should be_nil
91
113
  end
92
114
 
93
- Then /(.*) will contain (.*) image of size (.*)x(.*)/ do |url, format, width, height|
94
- data = get(url)
115
+ Then /(http.*) will contain (.*) image of size (.*)x(.*)/ do |url, format, width, height|
116
+ data = get(url.replace_s3_variables)
95
117
 
96
118
  @image.destroy! if @image
97
119
  @image = Magick::Image.from_blob(data).first
@@ -101,12 +123,30 @@ Then /(.*) will contain (.*) image of size (.*)x(.*)/ do |url, format, width, he
101
123
  @image.rows.should == height.to_i
102
124
  end
103
125
 
104
- Then /S3 bucket will not contain (.*)/ do |path|
105
- begin
106
- @bucket.objects.find(path)
107
- true.should eq(false, "object #{path} found in bucket")
108
- rescue S3::Error::NoSuchKey
109
- true.should == true
110
- end
126
+ Then /S3 object (.*) will contain (.*) image of size (.*)x(.*)/ do |key, format, width, height|
127
+ data = @bucket.objects[key].read
128
+
129
+ @image.destroy! if @image
130
+ @image = Magick::Image.from_blob(data).first
131
+
132
+ @image.format.should == format
133
+ @image.columns.should == width.to_i
134
+ @image.rows.should == height.to_i
135
+ end
136
+
137
+ Then /response body will contain (.*) image of size (.*)x(.*)/ do |format, width, height|
138
+ data = @response.body
139
+ Pathname.new('/tmp/out.jpg').open('w'){|io| io.write data}
140
+
141
+ @image.destroy! if @image
142
+ @image = Magick::Image.from_blob(data).first
143
+
144
+ @image.format.should == format
145
+ @image.columns.should == width.to_i
146
+ @image.rows.should == height.to_i
147
+ end
148
+
149
+ And /that image pixel at (.*)x(.*) should be of color (.*)/ do |x, y, color|
150
+ @image.pixel_color(x.to_i, y.to_i).to_color.sub(/^#/, '0x').should == color
111
151
  end
112
152
 
@@ -17,7 +17,19 @@ require "open3"
17
17
  require "thread"
18
18
  require 'tempfile'
19
19
  require 'RMagick'
20
- require 's3'
20
+ require 'aws-sdk'
21
+ require 'httpimagestore/aws_sdk_regions_hack'
22
+ require 'digest'
23
+
24
+ class String
25
+ def replace_s3_variables
26
+ string = self.dup
27
+ string.gsub!(/@AWS_ACCESS_KEY_ID@/, ENV['AWS_ACCESS_KEY_ID'])
28
+ string.gsub!(/@AWS_SECRET_ACCESS_KEY@/, ENV['AWS_SECRET_ACCESS_KEY'])
29
+ string.gsub!(/@AWS_S3_TEST_BUCKET@/, ENV['AWS_S3_TEST_BUCKET'])
30
+ string
31
+ end
32
+ end
21
33
 
22
34
  def gem_dir
23
35
  Pathname.new(__FILE__).dirname + '..' + '..'
@@ -35,22 +47,35 @@ def script(file)
35
47
  gem_dir + 'bin' + file
36
48
  end
37
49
 
50
+ def http_client
51
+ client = HTTPClient.new
52
+ #client.debug_dev = STDOUT
53
+ client
54
+ end
55
+
38
56
  def get(url)
39
- HTTPClient.new.get_content(URI.encode(url))
57
+ http_client.get_content(URI.encode(url))
40
58
  end
41
59
 
42
60
  def get_headers(url)
43
- HTTPClient.new.get(URI.encode(url)).headers
61
+ http_client.get(URI.encode(url)).headers
44
62
  end
45
63
 
64
+ @@running_cmd = {}
46
65
  def start_server(cmd, pid_file, log_file, test_url)
47
- stop_server(pid_file)
66
+ if @@running_cmd[pid_file]
67
+ return if @@running_cmd[pid_file] == cmd
68
+ stop_server(pid_file)
69
+ end
48
70
 
49
71
  fork do
50
72
  Daemon.daemonize(pid_file, log_file)
73
+ log_file = Pathname.new(log_file)
74
+ log_file.truncate(0) if log_file.exist?
51
75
  exec(cmd)
52
76
  end
53
- Process.wait
77
+
78
+ @@running_cmd[pid_file] = cmd
54
79
 
55
80
  ppid = Process.pid
56
81
  at_exit do
@@ -71,6 +96,7 @@ def stop_server(pid_file)
71
96
  pid_file = Pathname.new(pid_file)
72
97
  return unless pid_file.exist?
73
98
 
99
+ STDERR.puts http_client.get_content("http://localhost:3000/stats") if pid_file.to_s.include? 'httpimagestore'
74
100
  pid = pid_file.read.strip.to_i
75
101
 
76
102
  Timeout.timeout(20) do
@@ -80,6 +106,7 @@ def stop_server(pid_file)
80
106
  sleep 0.1
81
107
  end
82
108
  rescue Errno::ESRCH
109
+ @@running_cmd.delete pid_file.to_s
83
110
  pid_file.unlink
84
111
  end
85
112
  end
File without changes