httpimagestore 1.8.1 → 1.9.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.
Files changed (64) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +7 -7
  3. data/Gemfile.lock +20 -20
  4. data/README.md +165 -37
  5. data/Rakefile +7 -2
  6. data/VERSION +1 -1
  7. data/bin/httpimagestore +74 -41
  8. data/lib/httpimagestore/configuration/file.rb +20 -11
  9. data/lib/httpimagestore/configuration/handler.rb +96 -257
  10. data/lib/httpimagestore/configuration/handler/source_store_base.rb +37 -0
  11. data/lib/httpimagestore/configuration/handler/statement.rb +114 -0
  12. data/lib/httpimagestore/configuration/identify.rb +17 -9
  13. data/lib/httpimagestore/configuration/output.rb +33 -61
  14. data/lib/httpimagestore/configuration/path.rb +2 -2
  15. data/lib/httpimagestore/configuration/request_state.rb +131 -0
  16. data/lib/httpimagestore/configuration/s3.rb +41 -29
  17. data/lib/httpimagestore/configuration/thumbnailer.rb +189 -96
  18. data/lib/httpimagestore/configuration/validate_hmac.rb +170 -0
  19. data/lib/httpimagestore/error_reporter.rb +6 -1
  20. data/lib/httpimagestore/ruby_string_template.rb +10 -19
  21. metadata +40 -102
  22. data/.rspec +0 -1
  23. data/features/cache-control.feature +0 -41
  24. data/features/compatibility.feature +0 -165
  25. data/features/data-uri.feature +0 -55
  26. data/features/encoding.feature +0 -103
  27. data/features/error-reporting.feature +0 -281
  28. data/features/flexi.feature +0 -259
  29. data/features/health-check.feature +0 -29
  30. data/features/request-matching.feature +0 -211
  31. data/features/rewrite.feature +0 -122
  32. data/features/s3-store-and-thumbnail.feature +0 -82
  33. data/features/source-failover.feature +0 -71
  34. data/features/step_definitions/httpimagestore_steps.rb +0 -203
  35. data/features/storage.feature +0 -198
  36. data/features/support/env.rb +0 -116
  37. data/features/support/test-large.jpg +0 -0
  38. data/features/support/test.empty +0 -0
  39. data/features/support/test.jpg +0 -0
  40. data/features/support/test.png +0 -0
  41. data/features/support/test.txt +0 -1
  42. data/features/support/tiny.png +0 -0
  43. data/features/xid-forwarding.feature +0 -49
  44. data/httpimagestore.gemspec +0 -145
  45. data/load_test/load_test.1k.23a022f6e.m1.small-comp.csv +0 -3
  46. data/load_test/load_test.1k.ec9bde794.m1.small.csv +0 -4
  47. data/load_test/load_test.jmx +0 -317
  48. data/load_test/thumbnail_specs.csv +0 -11
  49. data/load_test/thumbnail_specs_v2.csv +0 -10
  50. data/spec/configuration_file_spec.rb +0 -333
  51. data/spec/configuration_handler_spec.rb +0 -255
  52. data/spec/configuration_identify_spec.rb +0 -67
  53. data/spec/configuration_output_spec.rb +0 -821
  54. data/spec/configuration_path_spec.rb +0 -138
  55. data/spec/configuration_s3_spec.rb +0 -911
  56. data/spec/configuration_source_failover_spec.rb +0 -101
  57. data/spec/configuration_spec.rb +0 -90
  58. data/spec/configuration_thumbnailer_spec.rb +0 -483
  59. data/spec/ruby_string_template_spec.rb +0 -61
  60. data/spec/spec_helper.rb +0 -89
  61. data/spec/support/compute.jpg +0 -0
  62. data/spec/support/cuba_response_env.rb +0 -40
  63. data/spec/support/full.cfg +0 -183
  64. data/spec/support/utf_string.txt +0 -1
@@ -0,0 +1,170 @@
1
+ require 'httpimagestore/configuration/handler/statement'
2
+ require 'securerandom'
3
+
4
+ module Configuration
5
+ class NoSecretKeySpecifiedError < ConfigurationError
6
+ def initialize
7
+ super 'no secret key given for validate_hmac (like secret="0f0f0...")'
8
+ end
9
+ end
10
+
11
+ class UnsupportedDigestError < ConfigurationError
12
+ def initialize(digest)
13
+ super "digest '#{digest}' is not supported"
14
+ end
15
+ end
16
+
17
+ class HMACAuthenticationFailedError < ArgumentError
18
+ def initialize(digest, msg)
19
+ super "HMAC URI authentication with digest '#{digest}' failed: #{msg}"
20
+ end
21
+ end
22
+
23
+ class HMACMismatchError < HMACAuthenticationFailedError
24
+ def initialize(expected_hmac, uri, digest)
25
+ super digest, "provided HMAC '#{expected_hmac}' for URI '#{uri}' is not valid"
26
+ end
27
+ end
28
+
29
+ class HMACMissingError < HMACAuthenticationFailedError
30
+ def initialize(hmac_qs_param_name, digest)
31
+ super digest, "HMAC query string parameter '#{hmac_qs_param_name}' not found"
32
+ end
33
+ end
34
+
35
+ class HMACMissingHeaderError < HMACAuthenticationFailedError
36
+ def initialize(digest, header_name)
37
+ super digest, "header '#{header_name}' not found in request body for HMAC verificaton"
38
+ end
39
+ end
40
+
41
+ class ValidateHMAC < HandlerStatement
42
+ include ConditionalInclusion
43
+
44
+ extend Stats
45
+ def_stats(
46
+ :total_hmac_validations,
47
+ :total_valid_hmac,
48
+ :total_invalid_hmac,
49
+ :total_lockpick_hmac
50
+ )
51
+
52
+ def self.new_with_common_options(configuration, node, hmac_qs_param_name, uri_source)
53
+ secret, digest, exclude, remove, lockpicks, remaining = *node.grab_attributes_with_remaining('secret', 'digest', 'exclude', 'remove', 'lockpicks')
54
+ conditions, remaining = *ConditionalInclusion.grab_conditions_with_remaining(remaining)
55
+ remaining.empty? or raise UnexpectedAttributesError.new(node, remaining)
56
+
57
+ obj = ValidateHMAC.new(hmac_qs_param_name, secret, lockpicks, digest, exclude, remove, uri_source)
58
+ obj.with_conditions(conditions)
59
+ obj
60
+ end
61
+
62
+ def initialize(hmac_qs_param_name, secret, lockpicks, digest, exclude, remove, uri_source)
63
+ @hmac_qs_param_name = hmac_qs_param_name
64
+ @secret = secret or raise NoSecretKeySpecifiedError
65
+ @digest = digest || 'sha1'
66
+
67
+ @exclude = (exclude || '').split(/ *, */)
68
+ @lockpicks = (lockpicks || '').split(/ *, */)
69
+ # always exclude hmac from hash computation
70
+ @exclude << @hmac_qs_param_name
71
+
72
+ # by default remove hmac for qs params but can be kept if remove=""
73
+ @remove = if remove
74
+ remove.split(/ *, */)
75
+ else
76
+ [@hmac_qs_param_name]
77
+ end
78
+
79
+ @uri_source = uri_source
80
+
81
+ # check if digest is valid
82
+ begin
83
+ OpenSSL::Digest.digest(@digest, 'blah')
84
+ rescue
85
+ raise UnsupportedDigestError.new(@digest)
86
+ end
87
+ end
88
+
89
+ attr_reader :digest
90
+
91
+ def realize(request_state)
92
+ expected_hmac = request_state.query_string[@hmac_qs_param_name] or raise HMACMissingError.new(@hmac_qs_param_name, @digest)
93
+
94
+ ValidateHMAC.stats.incr_total_hmac_validations
95
+
96
+ # we need to remove related query string params so we don't pass them as thumbnailer options
97
+ @remove.each do |rm|
98
+ log.debug "removing query string parameter '#{rm}' used for URI authentication"
99
+ request_state.query_string.delete(rm)
100
+ end
101
+
102
+ if lockpick = @lockpicks.detect{|lockpick| lockpick == expected_hmac}
103
+ # we try to get the URI if possible or else fail back to request_uri
104
+ # this is to help tracking where lockpicks are being used but still allow playing with APIs directly
105
+ # without need to set custom headers
106
+ lockpick_no = @lockpicks.find_index(lockpick) + 1
107
+ uri = @uri_source.call(self, request_state) rescue request_state.request_uri
108
+ uri = uri.gsub(/#{@exclude.last}=#{lockpick}/, "#{@exclude.last}=<lockpick #{lockpick_no} used>")
109
+
110
+ log.warn "valid lockpick provided! skipping URI HMAC validation for URI '#{uri}'"
111
+ ValidateHMAC.stats.incr_total_lockpick_hmac
112
+ return
113
+ end
114
+
115
+ uri = @uri_source.call(self, request_state) or fail "nil URI"
116
+ uri = @exclude.inject(uri) do |uri, ex|
117
+ uri.gsub(/(\?|&)#{ex}=.*?($|&)/, '\1')
118
+ end
119
+ uri.sub!(/(\?|&)$/, '')
120
+
121
+ digest = OpenSSL::Digest::Digest.new(@digest)
122
+
123
+ log.debug "validating URI '#{uri}' HMAC with digest '#{@digest}': expected HMAC '#{expected_hmac}'"
124
+ actual_hmac = OpenSSL::HMAC.hexdigest(digest, @secret, uri)
125
+
126
+ if actual_hmac != expected_hmac
127
+ sleep SecureRandom.random_number/10 # sleep some random time to make timing attack harder
128
+ log.warn "invalid HMAC with digest '#{@digest}' for URI '#{uri}'; expected HMAC '#{expected_hmac}'"
129
+ ValidateHMAC.stats.incr_total_invalid_hmac
130
+ raise HMACMismatchError.new(expected_hmac, uri, @digest)
131
+ else
132
+ ValidateHMAC.stats.incr_total_valid_hmac
133
+ end
134
+ end
135
+ end
136
+
137
+ class ValidateURIHMAC < ValidateHMAC
138
+ def self.match(node)
139
+ node.name == 'validate_uri_hmac'
140
+ end
141
+
142
+ def self.parse(configuration, node)
143
+ hmac_qs_param_name = node.grab_values('hmac').first
144
+ obj = self.new_with_common_options(configuration, node, hmac_qs_param_name, ->(obj, request_state){
145
+ request_state.request_uri
146
+ })
147
+ configuration.validators << obj
148
+ end
149
+ end
150
+
151
+ class ValidateHeaderHMAC < ValidateHMAC
152
+ def self.match(node)
153
+ node.name == 'validate_header_hmac'
154
+ end
155
+
156
+ def self.parse(configuration, node)
157
+ header_name, hmac_qs_param_name = *node.grab_values('header name', 'hmac')
158
+ header_name = header_name.upcase.gsub('_', '-')
159
+ obj = self.new_with_common_options(configuration, node, hmac_qs_param_name, ->(obj, request_state){
160
+ request_state.request_headers[header_name] or raise HMACMissingHeaderError.new(obj.digest, header_name)
161
+ })
162
+ configuration.validators << obj
163
+ end
164
+ end
165
+
166
+ Handler::register_node_parser ValidateURIHMAC
167
+ Handler::register_node_parser ValidateHeaderHMAC
168
+ StatsReporter << ValidateHMAC.stats
169
+ end
170
+
@@ -18,11 +18,16 @@ class ErrorReporter < Controller
18
18
 
19
19
  on error(
20
20
  Configuration::ZeroBodyLengthError,
21
- Configuration::NoSpecSelectedError
21
+ Configuration::NoSpecSelectedError,
22
+ Configuration::InvalidSpecError
22
23
  ) do |error|
23
24
  write_error 400, error
24
25
  end
25
26
 
27
+ on error(Configuration::HMACAuthenticationFailedError) do |error|
28
+ write_error 403, error
29
+ end
30
+
26
31
  on error Configuration::SourceFailoverAllFailedError do |error|
27
32
  if [Configuration::S3NoSuchKeyError, Configuration::NoSuchFileError].member? error.errors.first.class
28
33
  write_error 404, error
@@ -23,33 +23,20 @@ class RubyStringTemplate < String
23
23
  end
24
24
 
25
25
  def render(locals = {})
26
- template = self.to_s
27
- values = {}
28
-
29
- # use gsub with block instead!
30
- template.scan(/#\{[^\}]+\}/um).uniq.each do |placeholder|
26
+ self.gsub(/#\{[^\}]+\}/um) do |placeholder|
31
27
  name = placeholder.match(/#\{([^\}]*)\}/u).captures.first.to_sym
32
28
 
33
- value = nil
34
- @resolvers.find{|resolver| value = resolver.call(locals, name)} or fail NoValueForTemplatePlaceholderError.new(name, self)
35
- values[placeholder] = value.to_s
36
- end
37
-
38
- values.each_pair do |placeholder, value|
39
- template.gsub!(placeholder, value)
40
- end
41
-
42
- template
29
+ @resolvers.find do |resolver|
30
+ value = resolver.call(locals, name)
31
+ value and break value.to_s
32
+ end or fail NoValueForTemplatePlaceholderError.new(name, self)
33
+ end.to_s
43
34
  end
44
35
 
45
36
  def to_template
46
37
  self
47
38
  end
48
39
 
49
- #def inspect
50
- #super + "[#{@resolvers}]"
51
- #end
52
-
53
40
  def add_missing_resolver(&resolver)
54
41
  @resolvers << resolver
55
42
  end
@@ -59,6 +46,10 @@ class RubyStringTemplate < String
59
46
  new_template.add_missing_resolver(&resolver)
60
47
  new_template
61
48
  end
49
+
50
+ def inspect
51
+ "T<#{to_s}>"
52
+ end
62
53
  end
63
54
 
64
55
  class String
metadata CHANGED
@@ -1,52 +1,46 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpimagestore
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
5
- prerelease:
4
+ version: 1.9.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Jakub Pastuszek
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-08-28 00:00:00.000000000 Z
11
+ date: 2015-06-17 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: unicorn-cuba-base
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
21
- version: 1.2.2
19
+ version: '1.6'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
29
- version: 1.2.2
26
+ version: '1.6'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: httpthumbnailer-client
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
37
- version: 1.2.0
33
+ version: '1.3'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
45
- version: 1.2.0
40
+ version: '1.3'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: aws-sdk
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
@@ -62,23 +55,26 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: mime-types
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
59
+ - - <
60
+ - !ruby/object:Gem::Version
61
+ version: '2.99'
67
62
  - - ~>
68
63
  - !ruby/object:Gem::Version
69
- version: '1.17'
64
+ version: '2.6'
70
65
  type: :runtime
71
66
  prerelease: false
72
67
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
68
  requirements:
69
+ - - <
70
+ - !ruby/object:Gem::Version
71
+ version: '2.99'
75
72
  - - ~>
76
73
  - !ruby/object:Gem::Version
77
- version: '1.17'
74
+ version: '2.6'
78
75
  - !ruby/object:Gem::Dependency
79
76
  name: sdl4r
80
77
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
78
  requirements:
83
79
  - - ~>
84
80
  - !ruby/object:Gem::Version
@@ -86,7 +82,6 @@ dependencies:
86
82
  type: :runtime
87
83
  prerelease: false
88
84
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
85
  requirements:
91
86
  - - ~>
92
87
  - !ruby/object:Gem::Version
@@ -94,7 +89,6 @@ dependencies:
94
89
  - !ruby/object:Gem::Dependency
95
90
  name: msgpack
96
91
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
92
  requirements:
99
93
  - - ~>
100
94
  - !ruby/object:Gem::Version
@@ -102,7 +96,6 @@ dependencies:
102
96
  type: :runtime
103
97
  prerelease: false
104
98
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
99
  requirements:
107
100
  - - ~>
108
101
  - !ruby/object:Gem::Version
@@ -110,7 +103,6 @@ dependencies:
110
103
  - !ruby/object:Gem::Dependency
111
104
  name: addressable
112
105
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
106
  requirements:
115
107
  - - ~>
116
108
  - !ruby/object:Gem::Version
@@ -118,7 +110,6 @@ dependencies:
118
110
  type: :runtime
119
111
  prerelease: false
120
112
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
113
  requirements:
123
114
  - - ~>
124
115
  - !ruby/object:Gem::Version
@@ -126,23 +117,20 @@ dependencies:
126
117
  - !ruby/object:Gem::Dependency
127
118
  name: faraday
128
119
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
120
  requirements:
131
- - - ! '>='
121
+ - - ~>
132
122
  - !ruby/object:Gem::Version
133
123
  version: '0.8'
134
124
  type: :development
135
125
  prerelease: false
136
126
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
127
  requirements:
139
- - - ! '>='
128
+ - - ~>
140
129
  - !ruby/object:Gem::Version
141
130
  version: '0.8'
142
131
  - !ruby/object:Gem::Dependency
143
132
  name: rspec
144
133
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
134
  requirements:
147
135
  - - ~>
148
136
  - !ruby/object:Gem::Version
@@ -150,7 +138,6 @@ dependencies:
150
138
  type: :development
151
139
  prerelease: false
152
140
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
141
  requirements:
155
142
  - - ~>
156
143
  - !ruby/object:Gem::Version
@@ -158,39 +145,40 @@ dependencies:
158
145
  - !ruby/object:Gem::Dependency
159
146
  name: cucumber
160
147
  requirement: !ruby/object:Gem::Requirement
161
- none: false
162
148
  requirements:
163
- - - ! '>='
149
+ - - ~>
164
150
  - !ruby/object:Gem::Version
165
- version: '0'
151
+ version: '1.3'
166
152
  type: :development
167
153
  prerelease: false
168
154
  version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
155
  requirements:
171
- - - ! '>='
156
+ - - ~>
172
157
  - !ruby/object:Gem::Version
173
- version: '0'
158
+ version: '1.3'
174
159
  - !ruby/object:Gem::Dependency
175
160
  name: jeweler
176
161
  requirement: !ruby/object:Gem::Requirement
177
- none: false
178
162
  requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: 1.8.8
179
166
  - - ~>
180
167
  - !ruby/object:Gem::Version
181
- version: 1.8.4
168
+ version: '1.8'
182
169
  type: :development
183
170
  prerelease: false
184
171
  version_requirements: !ruby/object:Gem::Requirement
185
- none: false
186
172
  requirements:
173
+ - - ! '>='
174
+ - !ruby/object:Gem::Version
175
+ version: 1.8.8
187
176
  - - ~>
188
177
  - !ruby/object:Gem::Version
189
- version: 1.8.4
178
+ version: '1.8'
190
179
  - !ruby/object:Gem::Dependency
191
180
  name: rdoc
192
181
  requirement: !ruby/object:Gem::Requirement
193
- none: false
194
182
  requirements:
195
183
  - - ~>
196
184
  - !ruby/object:Gem::Version
@@ -198,7 +186,6 @@ dependencies:
198
186
  type: :development
199
187
  prerelease: false
200
188
  version_requirements: !ruby/object:Gem::Requirement
201
- none: false
202
189
  requirements:
203
190
  - - ~>
204
191
  - !ruby/object:Gem::Version
@@ -206,7 +193,6 @@ dependencies:
206
193
  - !ruby/object:Gem::Dependency
207
194
  name: daemon
208
195
  requirement: !ruby/object:Gem::Requirement
209
- none: false
210
196
  requirements:
211
197
  - - ~>
212
198
  - !ruby/object:Gem::Version
@@ -214,7 +200,6 @@ dependencies:
214
200
  type: :development
215
201
  prerelease: false
216
202
  version_requirements: !ruby/object:Gem::Requirement
217
- none: false
218
203
  requirements:
219
204
  - - ~>
220
205
  - !ruby/object:Gem::Version
@@ -222,7 +207,6 @@ dependencies:
222
207
  - !ruby/object:Gem::Dependency
223
208
  name: prawn
224
209
  requirement: !ruby/object:Gem::Requirement
225
- none: false
226
210
  requirements:
227
211
  - - '='
228
212
  - !ruby/object:Gem::Version
@@ -230,7 +214,6 @@ dependencies:
230
214
  type: :development
231
215
  prerelease: false
232
216
  version_requirements: !ruby/object:Gem::Requirement
233
- none: false
234
217
  requirements:
235
218
  - - '='
236
219
  - !ruby/object:Gem::Version
@@ -238,21 +221,19 @@ dependencies:
238
221
  - !ruby/object:Gem::Dependency
239
222
  name: httpthumbnailer
240
223
  requirement: !ruby/object:Gem::Requirement
241
- none: false
242
224
  requirements:
243
225
  - - ~>
244
226
  - !ruby/object:Gem::Version
245
- version: 1.2.0
227
+ version: '1.3'
246
228
  type: :development
247
229
  prerelease: false
248
230
  version_requirements: !ruby/object:Gem::Requirement
249
- none: false
250
231
  requirements:
251
232
  - - ~>
252
233
  - !ruby/object:Gem::Version
253
- version: 1.2.0
254
- description: Thumbnails images using httpthumbnailer and stored data on HTTP server
255
- (S3)
234
+ version: '1.3'
235
+ description: Configurable S3 or file system image storage and processing HTTP API
236
+ server. It is using HTTP Thumbnailer as image processing backend.
256
237
  email: jpastuszek@gmail.com
257
238
  executables:
258
239
  - httpimagestore
@@ -262,7 +243,6 @@ extra_rdoc_files:
262
243
  - README.md
263
244
  files:
264
245
  - .document
265
- - .rspec
266
246
  - Gemfile
267
247
  - Gemfile.lock
268
248
  - LICENSE.txt
@@ -270,86 +250,44 @@ files:
270
250
  - Rakefile
271
251
  - VERSION
272
252
  - bin/httpimagestore
273
- - features/cache-control.feature
274
- - features/compatibility.feature
275
- - features/data-uri.feature
276
- - features/encoding.feature
277
- - features/error-reporting.feature
278
- - features/flexi.feature
279
- - features/health-check.feature
280
- - features/request-matching.feature
281
- - features/rewrite.feature
282
- - features/s3-store-and-thumbnail.feature
283
- - features/source-failover.feature
284
- - features/step_definitions/httpimagestore_steps.rb
285
- - features/storage.feature
286
- - features/support/env.rb
287
- - features/support/test-large.jpg
288
- - features/support/test.empty
289
- - features/support/test.jpg
290
- - features/support/test.png
291
- - features/support/test.txt
292
- - features/support/tiny.png
293
- - features/xid-forwarding.feature
294
- - httpimagestore.gemspec
295
253
  - lib/httpimagestore/aws_sdk_regions_hack.rb
296
254
  - lib/httpimagestore/configuration.rb
297
255
  - lib/httpimagestore/configuration/file.rb
298
256
  - lib/httpimagestore/configuration/handler.rb
257
+ - lib/httpimagestore/configuration/handler/source_store_base.rb
258
+ - lib/httpimagestore/configuration/handler/statement.rb
299
259
  - lib/httpimagestore/configuration/identify.rb
300
260
  - lib/httpimagestore/configuration/output.rb
301
261
  - lib/httpimagestore/configuration/path.rb
262
+ - lib/httpimagestore/configuration/request_state.rb
302
263
  - lib/httpimagestore/configuration/s3.rb
303
264
  - lib/httpimagestore/configuration/source_failover.rb
304
265
  - lib/httpimagestore/configuration/thumbnailer.rb
266
+ - lib/httpimagestore/configuration/validate_hmac.rb
305
267
  - lib/httpimagestore/error_reporter.rb
306
268
  - lib/httpimagestore/ruby_string_template.rb
307
- - load_test/load_test.1k.23a022f6e.m1.small-comp.csv
308
- - load_test/load_test.1k.ec9bde794.m1.small.csv
309
- - load_test/load_test.jmx
310
- - load_test/thumbnail_specs.csv
311
- - load_test/thumbnail_specs_v2.csv
312
- - spec/configuration_file_spec.rb
313
- - spec/configuration_handler_spec.rb
314
- - spec/configuration_identify_spec.rb
315
- - spec/configuration_output_spec.rb
316
- - spec/configuration_path_spec.rb
317
- - spec/configuration_s3_spec.rb
318
- - spec/configuration_source_failover_spec.rb
319
- - spec/configuration_spec.rb
320
- - spec/configuration_thumbnailer_spec.rb
321
- - spec/ruby_string_template_spec.rb
322
- - spec/spec_helper.rb
323
- - spec/support/compute.jpg
324
- - spec/support/cuba_response_env.rb
325
- - spec/support/full.cfg
326
- - spec/support/utf_string.txt
327
269
  homepage: http://github.com/jpastuszek/httpimagestore
328
270
  licenses:
329
271
  - MIT
272
+ metadata: {}
330
273
  post_install_message:
331
274
  rdoc_options: []
332
275
  require_paths:
333
276
  - lib
334
277
  required_ruby_version: !ruby/object:Gem::Requirement
335
- none: false
336
278
  requirements:
337
279
  - - ! '>='
338
280
  - !ruby/object:Gem::Version
339
281
  version: '0'
340
- segments:
341
- - 0
342
- hash: 3314645469105412308
343
282
  required_rubygems_version: !ruby/object:Gem::Requirement
344
- none: false
345
283
  requirements:
346
284
  - - ! '>='
347
285
  - !ruby/object:Gem::Version
348
286
  version: '0'
349
287
  requirements: []
350
288
  rubyforge_project:
351
- rubygems_version: 1.8.23
289
+ rubygems_version: 2.4.7
352
290
  signing_key:
353
- specification_version: 3
354
- summary: HTTP based image storage and thumbnailer
291
+ specification_version: 4
292
+ summary: HTTP API server for image thumbnailing and storage
355
293
  test_files: []