image_vise 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/lib/image_vise/operators/expire_after.rb +17 -0
- data/lib/image_vise/render_engine.rb +9 -6
- data/lib/image_vise/version.rb +1 -1
- data/spec/image_vise/expire_after_spec.rb +35 -0
- data/spec/image_vise/render_engine_spec.rb +13 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15bac8714b52ca8cc0a2b57037ffb1db1ac85216
|
4
|
+
data.tar.gz: 1ff26e91dcea4e222f98caf695d92096822c2df1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 262b64839c5aceb9230ef958629535248a60a4f62ca4ef8cc7d923419ebdaec7491fb5b8978795212b81d8231d9d0ea3575972fe72a4eaf7ebd7b866b506387f
|
7
|
+
data.tar.gz: 7ef5cf55c0893907abb72cede01ddfc6a0cc824d5ebf0c0112df2789c1a0453ee03182311766372e10dd5db9d69885c89c6b30c28798b067802873c859b6e0f8
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Overrides the cache lifetime set in the output headers of the RenderEngine.
|
2
|
+
# Can be used to permit the requester to set the caching lifetime, instead
|
3
|
+
# of it being a configuration variable in the service performing the rendering
|
4
|
+
class ImageVise::ExpireAfter < Ks.strict(:seconds)
|
5
|
+
def initialize(seconds:)
|
6
|
+
unless seconds.is_a?(Integer) && seconds > 0
|
7
|
+
raise ArgumentError, "the :seconds parameter must be an Integer and must be above 0, but was %s" % seconds.inspect
|
8
|
+
end
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply!(_, metadata)
|
13
|
+
metadata[:expire_after_seconds] = seconds
|
14
|
+
end
|
15
|
+
|
16
|
+
ImageVise.add_operator 'expire_after', self
|
17
|
+
end
|
@@ -79,8 +79,8 @@
|
|
79
79
|
given_signature: signature,
|
80
80
|
secrets: ImageVise.secret_keys
|
81
81
|
)
|
82
|
-
render_destination_file, render_file_type, etag = process_image_request(image_request)
|
83
|
-
image_rack_response(render_destination_file, render_file_type, etag)
|
82
|
+
render_destination_file, render_file_type, etag, expire_after = process_image_request(image_request)
|
83
|
+
image_rack_response(render_destination_file, render_file_type, etag, expire_after)
|
84
84
|
rescue *permanent_failures => e
|
85
85
|
handle_request_error(e)
|
86
86
|
http_status_code = e.respond_to?(:http_status) ? e.http_status : 400
|
@@ -157,14 +157,14 @@
|
|
157
157
|
render_destination_file = Tempfile.new('imagevise-render').tap{|f| f.binmode }
|
158
158
|
|
159
159
|
# Do the actual imaging stuff
|
160
|
-
apply_pipeline(source_file.path, pipeline, source_file_type, render_destination_file.path)
|
160
|
+
expire_after = apply_pipeline(source_file.path, pipeline, source_file_type, render_destination_file.path)
|
161
161
|
|
162
162
|
# Catch this one early
|
163
163
|
render_destination_file.rewind
|
164
164
|
raise EmptyRender, "The rendered image was empty" if render_destination_file.size.zero?
|
165
165
|
|
166
166
|
render_file_type = detect_file_type(render_destination_file)
|
167
|
-
[render_destination_file, render_file_type, etag]
|
167
|
+
[render_destination_file, render_file_type, etag, expire_after]
|
168
168
|
ensure
|
169
169
|
ImageVise.close_and_unlink(source_file)
|
170
170
|
end
|
@@ -179,11 +179,11 @@
|
|
179
179
|
# @param render_destination_file[File] the File handle to the rendered image
|
180
180
|
# @param render_file_type[MagicBytes::FileType] the rendered file type
|
181
181
|
# @param etag[String] the ETag for the response
|
182
|
-
def image_rack_response(render_destination_file, render_file_type, etag)
|
182
|
+
def image_rack_response(render_destination_file, render_file_type, etag, expire_after)
|
183
183
|
response_headers = DEFAULT_HEADERS.merge({
|
184
184
|
'Content-Type' => render_file_type.mime,
|
185
185
|
'Content-Length' => '%d' % render_destination_file.size,
|
186
|
-
'Cache-Control' => IMAGE_CACHE_CONTROL %
|
186
|
+
'Cache-Control' => IMAGE_CACHE_CONTROL % expire_after.to_i,
|
187
187
|
'ETag' => etag
|
188
188
|
})
|
189
189
|
|
@@ -298,6 +298,9 @@
|
|
298
298
|
# If no operators touched the writer we are going to use the automatic format selection
|
299
299
|
writer = metadata.fetch(:writer, ImageVise::AutoWriter.new)
|
300
300
|
writer.write_image!(magick_image, metadata, render_to_path)
|
301
|
+
|
302
|
+
# Another metadata element is the expire_after, which we default to an app-wide setting
|
303
|
+
metadata.fetch(:expire_after_seconds, ImageVise.cache_lifetime_seconds)
|
301
304
|
ensure
|
302
305
|
# destroy all the loaded images explicitly
|
303
306
|
(image_list || []).map {|img| ImageVise.destroy(img) }
|
data/lib/image_vise/version.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe ImageVise::ExpireAfter do
|
4
|
+
it "raises on invalid arguments" do
|
5
|
+
expect {
|
6
|
+
described_class.new({})
|
7
|
+
}.to raise_error(ArgumentError)
|
8
|
+
|
9
|
+
expect {
|
10
|
+
described_class.new(seconds: '1')
|
11
|
+
}.to raise_error(ArgumentError)
|
12
|
+
|
13
|
+
expect {
|
14
|
+
described_class.new(seconds: -1)
|
15
|
+
}.to raise_error(ArgumentError)
|
16
|
+
|
17
|
+
expect {
|
18
|
+
described_class.new(seconds: 0)
|
19
|
+
}.to raise_error(ArgumentError)
|
20
|
+
|
21
|
+
described_class.new(seconds: 25)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "sets the :expire_after_seconds metadata key" do
|
25
|
+
subject = described_class.new(seconds: 4321)
|
26
|
+
|
27
|
+
fake_magick_image = double('Magick::Image')
|
28
|
+
metadata = {}
|
29
|
+
|
30
|
+
subject.apply!(fake_magick_image, metadata)
|
31
|
+
|
32
|
+
seconds_value = metadata.fetch(:expire_after_seconds)
|
33
|
+
expect(seconds_value).to eq(4321)
|
34
|
+
end
|
35
|
+
end
|
@@ -353,6 +353,19 @@ describe ImageVise::RenderEngine do
|
|
353
353
|
examine_image_from_string(last_response.body)
|
354
354
|
end
|
355
355
|
|
356
|
+
it 'sets a customized Expires: cache lifetime set via the pipeline' do
|
357
|
+
uri = Addressable::URI.parse(public_url_psd)
|
358
|
+
ImageVise.add_allowed_host!(uri.host)
|
359
|
+
ImageVise.add_secret_key!('1337ness')
|
360
|
+
|
361
|
+
p = ImageVise::Pipeline.new.geom(geometry_string: 'x220').expire_after(seconds: 20)
|
362
|
+
image_request = ImageVise::ImageRequest.new(src_url: uri.to_s, pipeline: p)
|
363
|
+
|
364
|
+
get image_request.to_path_params('1337ness')
|
365
|
+
|
366
|
+
expect(last_response.headers['Cache-Control']).to eq("public, no-transform, max-age=20")
|
367
|
+
end
|
368
|
+
|
356
369
|
it 'converts a PNG into a JPG applying a background fill' do
|
357
370
|
uri = Addressable::URI.parse(public_url_png_transparency)
|
358
371
|
ImageVise.add_allowed_host!(uri.host)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_vise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
@@ -227,6 +227,7 @@ files:
|
|
227
227
|
- lib/image_vise/operators/background_fill.rb
|
228
228
|
- lib/image_vise/operators/crop.rb
|
229
229
|
- lib/image_vise/operators/ellipse_stencil.rb
|
230
|
+
- lib/image_vise/operators/expire_after.rb
|
230
231
|
- lib/image_vise/operators/fit_crop.rb
|
231
232
|
- lib/image_vise/operators/force_jpg_out.rb
|
232
233
|
- lib/image_vise/operators/geom.rb
|
@@ -243,6 +244,7 @@ files:
|
|
243
244
|
- spec/image_vise/background_fill_spec.rb
|
244
245
|
- spec/image_vise/crop_spec.rb
|
245
246
|
- spec/image_vise/ellipse_stencil_spec.rb
|
247
|
+
- spec/image_vise/expire_after_spec.rb
|
246
248
|
- spec/image_vise/fetcher_file_spec.rb
|
247
249
|
- spec/image_vise/fetcher_http_spec.rb
|
248
250
|
- spec/image_vise/file_response_spec.rb
|
@@ -288,7 +290,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
288
290
|
version: '0'
|
289
291
|
requirements: []
|
290
292
|
rubyforge_project:
|
291
|
-
rubygems_version: 2.
|
293
|
+
rubygems_version: 2.5.2
|
292
294
|
signing_key:
|
293
295
|
specification_version: 4
|
294
296
|
summary: Runtime thumbnailing proxy
|