httpimagestore 1.6.0 → 1.7.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/Gemfile +4 -3
- data/Gemfile.lock +12 -16
- data/README.md +73 -0
- data/VERSION +1 -1
- data/bin/httpimagestore +7 -7
- data/features/data-uri.feature +55 -0
- data/features/error-reporting.feature +21 -3
- data/features/source-failover.feature +71 -0
- data/features/step_definitions/httpimagestore_steps.rb +27 -12
- data/features/storage.feature +26 -25
- data/features/support/tiny.png +0 -0
- data/features/xid-forwarding.feature +49 -0
- data/httpimagestore.gemspec +19 -23
- data/lib/httpimagestore/configuration/file.rb +6 -0
- data/lib/httpimagestore/configuration/handler.rb +4 -1
- data/lib/httpimagestore/configuration/identify.rb +2 -2
- data/lib/httpimagestore/configuration/output.rb +20 -1
- data/lib/httpimagestore/configuration/s3.rb +15 -9
- data/lib/httpimagestore/configuration/source_failover.rb +51 -0
- data/lib/httpimagestore/configuration/thumbnailer.rb +7 -7
- data/lib/httpimagestore/error_reporter.rb +9 -1
- data/lib/httpimagestore/ruby_string_template.rb +12 -7
- data/load_test/load_test.jmx +50 -77
- data/load_test/thumbnail_specs_v2.csv +10 -0
- data/spec/configuration_file_spec.rb +27 -2
- data/spec/configuration_identify_spec.rb +25 -2
- data/spec/configuration_s3_spec.rb +29 -3
- data/spec/configuration_source_failover_spec.rb +101 -0
- data/spec/configuration_thumbnailer_spec.rb +63 -8
- data/spec/ruby_string_template_spec.rb +4 -0
- data/spec/support/full.cfg +167 -33
- metadata +19 -23
- data/.idea/.name +0 -1
- data/.idea/.rakeTasks +0 -7
- data/.idea/codeStyleSettings.xml +0 -13
- data/.idea/dictionaries/wcc.xml +0 -8
- data/.idea/encodings.xml +0 -5
- data/.idea/httpimagestore.iml +0 -69
- data/.idea/jenkinsSettings.xml +0 -9
- data/.idea/misc.xml +0 -5
- data/.idea/modules.xml +0 -9
- data/.idea/scopes/scope_settings.xml +0 -5
- data/.idea/vcs.xml +0 -7
data/httpimagestore.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = "httpimagestore"
|
|
8
|
-
s.version = "1.
|
|
8
|
+
s.version = "1.7.0"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Jakub Pastuszek"]
|
|
12
|
-
s.date = "
|
|
12
|
+
s.date = "2014-07-28"
|
|
13
13
|
s.description = "Thumbnails images using httpthumbnailer and stored data on HTTP server (S3)"
|
|
14
14
|
s.email = "jpastuszek@gmail.com"
|
|
15
15
|
s.executables = ["httpimagestore"]
|
|
@@ -19,17 +19,6 @@ Gem::Specification.new do |s|
|
|
|
19
19
|
]
|
|
20
20
|
s.files = [
|
|
21
21
|
".document",
|
|
22
|
-
".idea/.name",
|
|
23
|
-
".idea/.rakeTasks",
|
|
24
|
-
".idea/codeStyleSettings.xml",
|
|
25
|
-
".idea/dictionaries/wcc.xml",
|
|
26
|
-
".idea/encodings.xml",
|
|
27
|
-
".idea/httpimagestore.iml",
|
|
28
|
-
".idea/jenkinsSettings.xml",
|
|
29
|
-
".idea/misc.xml",
|
|
30
|
-
".idea/modules.xml",
|
|
31
|
-
".idea/scopes/scope_settings.xml",
|
|
32
|
-
".idea/vcs.xml",
|
|
33
22
|
".rspec",
|
|
34
23
|
"Gemfile",
|
|
35
24
|
"Gemfile.lock",
|
|
@@ -40,11 +29,13 @@ Gem::Specification.new do |s|
|
|
|
40
29
|
"bin/httpimagestore",
|
|
41
30
|
"features/cache-control.feature",
|
|
42
31
|
"features/compatibility.feature",
|
|
32
|
+
"features/data-uri.feature",
|
|
43
33
|
"features/error-reporting.feature",
|
|
44
34
|
"features/flexi.feature",
|
|
45
35
|
"features/health-check.feature",
|
|
46
36
|
"features/request-matching.feature",
|
|
47
37
|
"features/s3-store-and-thumbnail.feature",
|
|
38
|
+
"features/source-failover.feature",
|
|
48
39
|
"features/step_definitions/httpimagestore_steps.rb",
|
|
49
40
|
"features/storage.feature",
|
|
50
41
|
"features/support/env.rb",
|
|
@@ -53,6 +44,8 @@ Gem::Specification.new do |s|
|
|
|
53
44
|
"features/support/test.jpg",
|
|
54
45
|
"features/support/test.png",
|
|
55
46
|
"features/support/test.txt",
|
|
47
|
+
"features/support/tiny.png",
|
|
48
|
+
"features/xid-forwarding.feature",
|
|
56
49
|
"httpimagestore.gemspec",
|
|
57
50
|
"lib/httpimagestore/aws_sdk_regions_hack.rb",
|
|
58
51
|
"lib/httpimagestore/configuration.rb",
|
|
@@ -62,6 +55,7 @@ Gem::Specification.new do |s|
|
|
|
62
55
|
"lib/httpimagestore/configuration/output.rb",
|
|
63
56
|
"lib/httpimagestore/configuration/path.rb",
|
|
64
57
|
"lib/httpimagestore/configuration/s3.rb",
|
|
58
|
+
"lib/httpimagestore/configuration/source_failover.rb",
|
|
65
59
|
"lib/httpimagestore/configuration/thumbnailer.rb",
|
|
66
60
|
"lib/httpimagestore/error_reporter.rb",
|
|
67
61
|
"lib/httpimagestore/ruby_string_template.rb",
|
|
@@ -69,12 +63,14 @@ Gem::Specification.new do |s|
|
|
|
69
63
|
"load_test/load_test.1k.ec9bde794.m1.small.csv",
|
|
70
64
|
"load_test/load_test.jmx",
|
|
71
65
|
"load_test/thumbnail_specs.csv",
|
|
66
|
+
"load_test/thumbnail_specs_v2.csv",
|
|
72
67
|
"spec/configuration_file_spec.rb",
|
|
73
68
|
"spec/configuration_handler_spec.rb",
|
|
74
69
|
"spec/configuration_identify_spec.rb",
|
|
75
70
|
"spec/configuration_output_spec.rb",
|
|
76
71
|
"spec/configuration_path_spec.rb",
|
|
77
72
|
"spec/configuration_s3_spec.rb",
|
|
73
|
+
"spec/configuration_source_failover_spec.rb",
|
|
78
74
|
"spec/configuration_spec.rb",
|
|
79
75
|
"spec/configuration_thumbnailer_spec.rb",
|
|
80
76
|
"spec/ruby_string_template_spec.rb",
|
|
@@ -86,15 +82,15 @@ Gem::Specification.new do |s|
|
|
|
86
82
|
s.homepage = "http://github.com/jpastuszek/httpimagestore"
|
|
87
83
|
s.licenses = ["MIT"]
|
|
88
84
|
s.require_paths = ["lib"]
|
|
89
|
-
s.rubygems_version = "1.8.
|
|
85
|
+
s.rubygems_version = "1.8.23"
|
|
90
86
|
s.summary = "HTTP based image storage and thumbnailer"
|
|
91
87
|
|
|
92
88
|
if s.respond_to? :specification_version then
|
|
93
89
|
s.specification_version = 3
|
|
94
90
|
|
|
95
91
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
96
|
-
s.add_runtime_dependency(%q<unicorn-cuba-base>, ["~> 1.
|
|
97
|
-
s.add_runtime_dependency(%q<httpthumbnailer-client>, ["~> 1.
|
|
92
|
+
s.add_runtime_dependency(%q<unicorn-cuba-base>, ["~> 1.2.0"])
|
|
93
|
+
s.add_runtime_dependency(%q<httpthumbnailer-client>, ["~> 1.2.0"])
|
|
98
94
|
s.add_runtime_dependency(%q<aws-sdk>, ["~> 1.10"])
|
|
99
95
|
s.add_runtime_dependency(%q<mime-types>, ["~> 1.17"])
|
|
100
96
|
s.add_runtime_dependency(%q<sdl4r>, ["~> 0.9"])
|
|
@@ -106,10 +102,10 @@ Gem::Specification.new do |s|
|
|
|
106
102
|
s.add_development_dependency(%q<rdoc>, ["~> 3.9"])
|
|
107
103
|
s.add_development_dependency(%q<daemon>, ["~> 1"])
|
|
108
104
|
s.add_development_dependency(%q<prawn>, ["= 0.8.4"])
|
|
109
|
-
s.add_development_dependency(%q<httpthumbnailer>, ["
|
|
105
|
+
s.add_development_dependency(%q<httpthumbnailer>, ["~> 1.2.0"])
|
|
110
106
|
else
|
|
111
|
-
s.add_dependency(%q<unicorn-cuba-base>, ["~> 1.
|
|
112
|
-
s.add_dependency(%q<httpthumbnailer-client>, ["~> 1.
|
|
107
|
+
s.add_dependency(%q<unicorn-cuba-base>, ["~> 1.2.0"])
|
|
108
|
+
s.add_dependency(%q<httpthumbnailer-client>, ["~> 1.2.0"])
|
|
113
109
|
s.add_dependency(%q<aws-sdk>, ["~> 1.10"])
|
|
114
110
|
s.add_dependency(%q<mime-types>, ["~> 1.17"])
|
|
115
111
|
s.add_dependency(%q<sdl4r>, ["~> 0.9"])
|
|
@@ -121,11 +117,11 @@ Gem::Specification.new do |s|
|
|
|
121
117
|
s.add_dependency(%q<rdoc>, ["~> 3.9"])
|
|
122
118
|
s.add_dependency(%q<daemon>, ["~> 1"])
|
|
123
119
|
s.add_dependency(%q<prawn>, ["= 0.8.4"])
|
|
124
|
-
s.add_dependency(%q<httpthumbnailer>, ["
|
|
120
|
+
s.add_dependency(%q<httpthumbnailer>, ["~> 1.2.0"])
|
|
125
121
|
end
|
|
126
122
|
else
|
|
127
|
-
s.add_dependency(%q<unicorn-cuba-base>, ["~> 1.
|
|
128
|
-
s.add_dependency(%q<httpthumbnailer-client>, ["~> 1.
|
|
123
|
+
s.add_dependency(%q<unicorn-cuba-base>, ["~> 1.2.0"])
|
|
124
|
+
s.add_dependency(%q<httpthumbnailer-client>, ["~> 1.2.0"])
|
|
129
125
|
s.add_dependency(%q<aws-sdk>, ["~> 1.10"])
|
|
130
126
|
s.add_dependency(%q<mime-types>, ["~> 1.17"])
|
|
131
127
|
s.add_dependency(%q<sdl4r>, ["~> 0.9"])
|
|
@@ -137,7 +133,7 @@ Gem::Specification.new do |s|
|
|
|
137
133
|
s.add_dependency(%q<rdoc>, ["~> 3.9"])
|
|
138
134
|
s.add_dependency(%q<daemon>, ["~> 1"])
|
|
139
135
|
s.add_dependency(%q<prawn>, ["= 0.8.4"])
|
|
140
|
-
s.add_dependency(%q<httpthumbnailer>, ["
|
|
136
|
+
s.add_dependency(%q<httpthumbnailer>, ["~> 1.2.0"])
|
|
141
137
|
end
|
|
142
138
|
end
|
|
143
139
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'httpimagestore/configuration/path'
|
|
2
2
|
require 'httpimagestore/configuration/handler'
|
|
3
|
+
require 'httpimagestore/configuration/source_failover'
|
|
3
4
|
require 'pathname'
|
|
4
5
|
require 'uri'
|
|
5
6
|
|
|
@@ -54,6 +55,10 @@ module Configuration
|
|
|
54
55
|
|
|
55
56
|
storage_path
|
|
56
57
|
end
|
|
58
|
+
|
|
59
|
+
def to_s
|
|
60
|
+
"FileSource[image_name: '#{@image_name}' root_dir: '#{@root_dir}' path_spec: '#{@path_spec}']"
|
|
61
|
+
end
|
|
57
62
|
end
|
|
58
63
|
|
|
59
64
|
class FileSource < FileSourceStoreBase
|
|
@@ -90,6 +95,7 @@ module Configuration
|
|
|
90
95
|
end
|
|
91
96
|
end
|
|
92
97
|
Handler::register_node_parser FileSource
|
|
98
|
+
SourceFailover::register_node_parser FileSource
|
|
93
99
|
|
|
94
100
|
class FileStore < FileSourceStoreBase
|
|
95
101
|
include ClassLogging
|
|
@@ -60,7 +60,7 @@ module Configuration
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
def initialize(body = '', matches = {}, path = '', query_string = {}, memory_limit = MemoryLimit.new)
|
|
63
|
+
def initialize(body = '', matches = {}, path = '', query_string = {}, memory_limit = MemoryLimit.new, headers = {})
|
|
64
64
|
super() do |request_state, name|
|
|
65
65
|
# note that request_state may be different object when useing with_locals that creates duplicate
|
|
66
66
|
request_state[name] = request_state.generate_meta_variable(name) or raise VariableNotDefinedError.new(name)
|
|
@@ -76,11 +76,14 @@ module Configuration
|
|
|
76
76
|
@images = Images.new(memory_limit)
|
|
77
77
|
@memory_limit = memory_limit
|
|
78
78
|
@output_callback = nil
|
|
79
|
+
|
|
80
|
+
@headers = headers
|
|
79
81
|
end
|
|
80
82
|
|
|
81
83
|
attr_reader :body
|
|
82
84
|
attr_reader :images
|
|
83
85
|
attr_reader :memory_limit
|
|
86
|
+
attr_reader :headers
|
|
84
87
|
|
|
85
88
|
def with_locals(locals)
|
|
86
89
|
log.debug "using additional local variables: #{locals}"
|
|
@@ -8,7 +8,7 @@ module Configuration
|
|
|
8
8
|
|
|
9
9
|
extend Stats
|
|
10
10
|
def_stats(
|
|
11
|
-
:total_identify_requests,
|
|
11
|
+
:total_identify_requests,
|
|
12
12
|
:total_identify_requests_bytes
|
|
13
13
|
)
|
|
14
14
|
|
|
@@ -42,7 +42,7 @@ module Configuration
|
|
|
42
42
|
Identify.stats.incr_total_identify_requests
|
|
43
43
|
Identify.stats.incr_total_identify_requests_bytes image.data.bytesize
|
|
44
44
|
|
|
45
|
-
id = client.identify(image.data)
|
|
45
|
+
id = client.with_headers(request_state.headers).identify(image.data)
|
|
46
46
|
|
|
47
47
|
image.mime_type = id.mime_type if id.mime_type
|
|
48
48
|
image.width = id.width if id.width
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'httpimagestore/configuration/handler'
|
|
2
2
|
require 'httpimagestore/ruby_string_template'
|
|
3
3
|
require 'uri'
|
|
4
|
+
require 'base64'
|
|
4
5
|
|
|
5
6
|
module Configuration
|
|
6
7
|
class StorePathNotSetForImage < ConfigurationError
|
|
@@ -131,7 +132,7 @@ module Configuration
|
|
|
131
132
|
configuration.output and raise StatementCollisionError.new(node, 'output')
|
|
132
133
|
image_name = node.grab_values('image name').first
|
|
133
134
|
cache_control = node.grab_attributes('cache-control').first
|
|
134
|
-
configuration.output =
|
|
135
|
+
configuration.output = self.new(image_name, cache_control)
|
|
135
136
|
end
|
|
136
137
|
|
|
137
138
|
def initialize(name, cache_control)
|
|
@@ -158,6 +159,24 @@ module Configuration
|
|
|
158
159
|
end
|
|
159
160
|
Handler::register_node_parser OutputImage
|
|
160
161
|
|
|
162
|
+
class OutputDataURIImage < OutputImage
|
|
163
|
+
def self.match(node)
|
|
164
|
+
node.name == 'output_data_uri_image'
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def realize(request_state)
|
|
168
|
+
image = request_state.images[@name]
|
|
169
|
+
fail "image '#{@name}' needs to be identified first to be used in data URI output" unless image.mime_type
|
|
170
|
+
|
|
171
|
+
cache_control = @cache_control
|
|
172
|
+
request_state.output do
|
|
173
|
+
res['Cache-Control'] = cache_control if cache_control
|
|
174
|
+
write 200, 'text/uri-list', "data:#{image.mime_type};base64,#{Base64.strict_encode64(image.data)}"
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
Handler::register_node_parser OutputDataURIImage
|
|
179
|
+
|
|
161
180
|
class OutputStorePath < OutputMultiBase
|
|
162
181
|
def self.match(node)
|
|
163
182
|
node.name == 'output_store_path'
|
|
@@ -4,6 +4,7 @@ require 'msgpack'
|
|
|
4
4
|
require 'httpimagestore/aws_sdk_regions_hack'
|
|
5
5
|
require 'httpimagestore/configuration/path'
|
|
6
6
|
require 'httpimagestore/configuration/handler'
|
|
7
|
+
require 'httpimagestore/configuration/source_failover'
|
|
7
8
|
|
|
8
9
|
module Configuration
|
|
9
10
|
class S3NotConfiguredError < ConfigurationError
|
|
@@ -43,7 +44,7 @@ module Configuration
|
|
|
43
44
|
node.grab_values
|
|
44
45
|
node.required_attributes('key', 'secret')
|
|
45
46
|
node.valid_attribute_values('ssl', true, false, nil)
|
|
46
|
-
|
|
47
|
+
|
|
47
48
|
key, secret, ssl = node.grab_attributes('key', 'secret', 'ssl')
|
|
48
49
|
ssl = true if ssl.nil?
|
|
49
50
|
|
|
@@ -191,7 +192,7 @@ module Configuration
|
|
|
191
192
|
class CacheObject < S3Object
|
|
192
193
|
extend Stats
|
|
193
194
|
def_stats(
|
|
194
|
-
:total_s3_cache_hits,
|
|
195
|
+
:total_s3_cache_hits,
|
|
195
196
|
:total_s3_cache_misses,
|
|
196
197
|
:total_s3_cache_errors,
|
|
197
198
|
)
|
|
@@ -274,7 +275,7 @@ module Configuration
|
|
|
274
275
|
|
|
275
276
|
extend Stats
|
|
276
277
|
def_stats(
|
|
277
|
-
:total_s3_store,
|
|
278
|
+
:total_s3_store,
|
|
278
279
|
:total_s3_store_bytes,
|
|
279
280
|
:total_s3_source,
|
|
280
281
|
:total_s3_source_bytes
|
|
@@ -286,18 +287,18 @@ module Configuration
|
|
|
286
287
|
node.required_attributes('bucket', 'path')
|
|
287
288
|
node.valid_attribute_values('public_access', true, false, nil)
|
|
288
289
|
|
|
289
|
-
bucket, path_spec, public_access, cache_control, prefix, cache_root, if_image_name_on =
|
|
290
|
+
bucket, path_spec, public_access, cache_control, prefix, cache_root, if_image_name_on =
|
|
290
291
|
*node.grab_attributes('bucket', 'path', 'public', 'cache-control', 'prefix', 'cache-root', 'if-image-name-on')
|
|
291
292
|
public_access = false if public_access.nil?
|
|
292
293
|
prefix = '' if prefix.nil?
|
|
293
294
|
|
|
294
295
|
self.new(
|
|
295
|
-
configuration.global,
|
|
296
|
-
image_name,
|
|
296
|
+
configuration.global,
|
|
297
|
+
image_name,
|
|
297
298
|
InclusionMatcher.new(image_name, if_image_name_on),
|
|
298
|
-
bucket,
|
|
299
|
-
path_spec,
|
|
300
|
-
public_access,
|
|
299
|
+
bucket,
|
|
300
|
+
path_spec,
|
|
301
|
+
public_access,
|
|
301
302
|
cache_control,
|
|
302
303
|
prefix,
|
|
303
304
|
cache_root
|
|
@@ -395,8 +396,13 @@ module Configuration
|
|
|
395
396
|
end
|
|
396
397
|
end
|
|
397
398
|
end
|
|
399
|
+
|
|
400
|
+
def to_s
|
|
401
|
+
"S3Source[image_name: '#{@image_name}' bucket: '#{@bucket}' prefix: '#{@prefix}' path_spec: '#{@path_spec}']"
|
|
402
|
+
end
|
|
398
403
|
end
|
|
399
404
|
Handler::register_node_parser S3Source
|
|
405
|
+
SourceFailover::register_node_parser S3Source
|
|
400
406
|
|
|
401
407
|
class S3Store < S3SourceStoreBase
|
|
402
408
|
def self.match(node)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'httpimagestore/configuration/handler'
|
|
2
|
+
|
|
3
|
+
module Configuration
|
|
4
|
+
class SourceFailoverAllFailedError < ConfigurationError
|
|
5
|
+
attr_reader :sources, :errors
|
|
6
|
+
|
|
7
|
+
def initialize(sources, errors)
|
|
8
|
+
@sources = sources
|
|
9
|
+
@errors = errors
|
|
10
|
+
super "all sources failed: #{sources.zip(errors).map{|s, e| "#{s}(#{e.class.name}: #{e.message})"}.join(', ')}"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class SourceFailover < Scope
|
|
15
|
+
include ClassLogging
|
|
16
|
+
|
|
17
|
+
def self.match(node)
|
|
18
|
+
node.name == 'source_failover'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.parse(configuration, node)
|
|
22
|
+
# support only sources
|
|
23
|
+
handler_configuration = Struct.new(
|
|
24
|
+
:global,
|
|
25
|
+
:sources
|
|
26
|
+
).new
|
|
27
|
+
handler_configuration.global = configuration.global
|
|
28
|
+
handler_configuration.sources = []
|
|
29
|
+
|
|
30
|
+
failover = self.new(handler_configuration)
|
|
31
|
+
configuration.sources << failover
|
|
32
|
+
failover.parse(node)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def realize(request_state)
|
|
36
|
+
errors = []
|
|
37
|
+
@configuration.sources.each do |source|
|
|
38
|
+
begin
|
|
39
|
+
log.debug "trying source: #{source}"
|
|
40
|
+
return source.realize(request_state) unless source.respond_to? :excluded? and source.excluded?(request_state)
|
|
41
|
+
rescue => error
|
|
42
|
+
errors << error
|
|
43
|
+
log.warn "source #{source} failed; trying next source", error
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
log.error "all sources: #{@configuration.sources.map(&:to_s).join(', ')} failed; giving up"
|
|
47
|
+
raise SourceFailoverAllFailedError.new(@configuration.sources.to_a, errors)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
Handler::register_node_parser SourceFailover
|
|
51
|
+
end
|
|
@@ -36,7 +36,7 @@ module Configuration
|
|
|
36
36
|
|
|
37
37
|
extend Stats
|
|
38
38
|
def_stats(
|
|
39
|
-
:total_thumbnail_requests,
|
|
39
|
+
:total_thumbnail_requests,
|
|
40
40
|
:total_thumbnail_requests_bytes,
|
|
41
41
|
:total_thumbnail_thumbnails,
|
|
42
42
|
:total_thumbnail_thumbnails_bytes
|
|
@@ -134,9 +134,9 @@ module Configuration
|
|
|
134
134
|
matcher = InclusionMatcher.new(source_image_name, node.grab_attributes('if-image-name-on').first) if use_multipart_api
|
|
135
135
|
|
|
136
136
|
configuration.processors << self.new(
|
|
137
|
-
configuration.global,
|
|
138
|
-
source_image_name,
|
|
139
|
-
specs,
|
|
137
|
+
configuration.global,
|
|
138
|
+
source_image_name,
|
|
139
|
+
specs,
|
|
140
140
|
use_multipart_api,
|
|
141
141
|
matcher
|
|
142
142
|
)
|
|
@@ -177,7 +177,7 @@ module Configuration
|
|
|
177
177
|
logger = log
|
|
178
178
|
|
|
179
179
|
begin
|
|
180
|
-
thumbnails = client.thumbnail(source_image.data) do
|
|
180
|
+
thumbnails = client.with_headers(request_state.headers).thumbnail(source_image.data) do
|
|
181
181
|
rendered_specs.each_pair do |name, spec|
|
|
182
182
|
begin
|
|
183
183
|
thumbnail(*spec)
|
|
@@ -202,7 +202,7 @@ module Configuration
|
|
|
202
202
|
if thumbnail.kind_of? HTTPThumbnailerClient::HTTPThumbnailerClientError
|
|
203
203
|
error = thumbnail
|
|
204
204
|
log.warn 'got single thumbnail error', error
|
|
205
|
-
raise ThumbnailingError.new(@source_image_name, name, error)
|
|
205
|
+
raise ThumbnailingError.new(@source_image_name, name, error)
|
|
206
206
|
end
|
|
207
207
|
end
|
|
208
208
|
|
|
@@ -215,7 +215,7 @@ module Configuration
|
|
|
215
215
|
log.info "thumbnailing '#{@source_image_name}' to '#{name}' with spec: #{rendered_spec}"
|
|
216
216
|
|
|
217
217
|
begin
|
|
218
|
-
thumbnail = client.thumbnail(source_image.data, *rendered_spec)
|
|
218
|
+
thumbnail = client.with_headers(request_state.headers).thumbnail(source_image.data, *rendered_spec)
|
|
219
219
|
request_state.memory_limit.borrow(thumbnail.data.bytesize, "thumbnail '#{name}'")
|
|
220
220
|
|
|
221
221
|
input_mime_type = thumbnail.input_mime_type
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class ErrorReporter <
|
|
1
|
+
class ErrorReporter < Controller
|
|
2
2
|
self.define do
|
|
3
3
|
on error(
|
|
4
4
|
Configuration::S3NoSuchKeyError,
|
|
@@ -20,6 +20,14 @@ class ErrorReporter < Controler
|
|
|
20
20
|
write_error 400, error
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
on error Configuration::SourceFailoverAllFailedError do |error|
|
|
24
|
+
if [Configuration::S3NoSuchKeyError, Configuration::NoSuchFileError].member? error.errors.first.class
|
|
25
|
+
write_error 404, error
|
|
26
|
+
else
|
|
27
|
+
write_error 500, error
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
23
31
|
run DefaultErrorReporter
|
|
24
32
|
end
|
|
25
33
|
end
|
|
@@ -4,22 +4,27 @@ class RubyStringTemplate
|
|
|
4
4
|
super "no value for '\#{#{name}}' in template '#{template}'"
|
|
5
5
|
end
|
|
6
6
|
end
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
def initialize(template, &resolver)
|
|
9
9
|
@template = template.to_s
|
|
10
10
|
@resolver = resolver ? resolver : ->(locals, name){locals[name]}
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def render(locals = {})
|
|
14
|
-
template = @template
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
template = @template.dup
|
|
15
|
+
values = {}
|
|
16
|
+
|
|
17
|
+
template.scan(/#\{[^\}]+\}/um).uniq.each do |placeholder|
|
|
18
|
+
name = placeholder.match(/#\{([^\}]*)\}/u).captures.first.to_sym
|
|
18
19
|
value = @resolver.call(locals, name)
|
|
19
20
|
value or fail NoValueForTemplatePlaceholderError.new(name, @template)
|
|
20
|
-
|
|
21
|
-
template = template.gsub(tag, value)
|
|
21
|
+
values[placeholder] = value.to_s
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
values.each_pair do |placeholder, value|
|
|
25
|
+
template.gsub!(placeholder, value)
|
|
26
|
+
end
|
|
27
|
+
|
|
23
28
|
template
|
|
24
29
|
end
|
|
25
30
|
end
|