image_vise 0.6.0 → 0.8.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1be0d4d8682d0436356b4ea5e0023869b50709dd
4
- data.tar.gz: de463d93ee8e7e55c0cfa59db9a5c0dee9b91a25
2
+ SHA256:
3
+ metadata.gz: 448a0d9a3decdcb6af4a3c0dc52fbed811bca85a8ba1df2775916ee164dffdcf
4
+ data.tar.gz: 3bb7300d2622d442ebe559195276e1ab753a9f1268b955fe2427362041f35036
5
5
  SHA512:
6
- metadata.gz: e93df7c9c8723663ab09a7ba09916f5327ec7b2a71e63818b7e4bf72d851dcb119fd21c9133bd6e97158fc672e9ac64043db9f6f897a5dd9b051dd7e706c5315
7
- data.tar.gz: 15e293b3e33026a78f486ba2921a8df5a1af1b51fb08c3984864b81316697c14979715148e39eaa00f0b85a7228cc0a79f19a7b8f41002558f6e86ceaec507cd
6
+ metadata.gz: c71485f40a843adfc42887ef0d3766df61c83457bb3cbc92763e1c172c82a74ba7b1aba8472f9f16e79a2a35469648d361e7f6a0c85f5bfddba2f8f662283b5d
7
+ data.tar.gz: 6863b83f51d044589e20c6cf40ff6e6843f148374cea3a8c036a9af8fef99f626f6ef941a83bd80a44159eaed2a1a85122c7a2444510a006fddf8825f3195954
data/.gitignore CHANGED
@@ -6,3 +6,4 @@ Gemfile.lock
6
6
  *.log
7
7
  pkg
8
8
  coverage
9
+ .ruby-version
@@ -1,13 +1,10 @@
1
1
  rvm:
2
- - 2.2.10
3
- - 2.3.7
4
2
  - 2.4.4
5
3
  - 2.5.1
4
+ - 2.6.2
6
5
  sudo: false
7
6
  cache: bundler
8
-
9
7
  env:
10
8
  global:
11
9
  - SKIP_INTERACTIVE=yes
12
- before_install: gem install bundler
13
10
  script: bundle exec rspec
@@ -0,0 +1,2 @@
1
+ ## 0.8.2
2
+ * Change format_parser required version to allow > 0.24
@@ -1,7 +1,7 @@
1
1
  # Anywhere in your app code
2
2
  module ImageViseAppsignal
3
3
  ImageVise::RenderEngine.prepend self
4
- ImageVise::Measurometer.drivers << Appsignal # to obtain ImageVise instrumentation
4
+ Measurometer.drivers << Appsignal # to obtain ImageVise instrumentation
5
5
  def setup_error_handling(rack_env)
6
6
  txn = Appsignal::Transaction.current
7
7
  txn.set_action('%s#%s' % [self.class, 'call'])
@@ -21,20 +21,21 @@ Gem::Specification.new do |spec|
21
21
  else
22
22
  raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
23
  end
24
-
24
+
25
25
  spec.files = `git ls-files -z`.split("\x0")
26
26
  spec.bindir = "exe"
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
30
  spec.add_dependency 'patron', '~> 0.9'
31
- spec.add_dependency 'rmagick', '~> 2.15'
31
+ spec.add_dependency 'rmagick', '~> 3'
32
32
  spec.add_dependency 'ks'
33
33
  spec.add_dependency 'rack', '>= 1', '< 3'
34
- spec.add_dependency 'format_parser', '>= 0.12.1', '< 1.0'
34
+ spec.add_dependency 'format_parser', '~> 0.25'
35
+ spec.add_dependency 'measurometer', '~> 1'
35
36
 
36
37
  spec.add_development_dependency 'magic_bytes', '~> 1'
37
- spec.add_development_dependency "bundler", "~> 1.7"
38
+ spec.add_development_dependency "bundler"
38
39
  spec.add_development_dependency "rake", "~> 12.2"
39
40
  spec.add_development_dependency "rack-test"
40
41
  spec.add_development_dependency "rspec", "~> 3"
@@ -2,10 +2,10 @@ require 'ks'
2
2
  require 'json'
3
3
  require 'patron'
4
4
  require 'rmagick'
5
- require 'magic_bytes'
6
5
  require 'thread'
7
6
  require 'base64'
8
7
  require 'rack'
8
+ require 'measurometer'
9
9
  require 'format_parser'
10
10
 
11
11
  class ImageVise
@@ -27,7 +27,9 @@ class ImageVise
27
27
  @allowed_glob_patterns = Set.new
28
28
  @fetchers = {}
29
29
  @cache_lifetime = DEFAULT_CACHE_LIFETIME
30
-
30
+
31
+ const_set(:Measurometer, ::Measurometer)
32
+
31
33
  class << self
32
34
  # Resets all allowed hosts
33
35
  def reset_allowed_hosts!
@@ -165,7 +167,7 @@ class ImageVise
165
167
  return unless maybe_image
166
168
  return unless maybe_image.respond_to?(:destroy!)
167
169
  return if maybe_image.destroyed?
168
- ImageVise::Measurometer.instrument('image_vise.image_destroy_dealloc') do
170
+ Measurometer.instrument('image_vise.image_destroy_dealloc') do
169
171
  maybe_image.destroy!
170
172
  end
171
173
  end
@@ -175,7 +177,7 @@ class ImageVise
175
177
  # in scope but not yet set to an image) we take the possibility of nils into account.
176
178
  def self.close_and_unlink(maybe_tempfile)
177
179
  return unless maybe_tempfile
178
- ImageVise::Measurometer.instrument('image_vise.tempfile_unlink') do
180
+ Measurometer.instrument('image_vise.tempfile_unlink') do
179
181
  maybe_tempfile.close unless maybe_tempfile.closed?
180
182
  maybe_tempfile.unlink if maybe_tempfile.respond_to?(:unlink)
181
183
  end
@@ -14,11 +14,11 @@ class ImageVise::ImageRequest < Ks.strict(:src_url, :pipeline)
14
14
 
15
15
  # Check the signature before decoding JSON (since we will be creating symbols)
16
16
  unless valid_signature?(base64_encoded_params, given_signature, secrets)
17
- ImageVise::Measurometer.increment_counter('image_vise.params.invalid_signatures', 1)
17
+ Measurometer.increment_counter('image_vise.params.invalid_signatures', 1)
18
18
  raise SignatureError, "Invalid or missing signature"
19
19
  end
20
20
 
21
- ImageVise::Measurometer.increment_counter('image_vise.params.valid_signatures', 1)
21
+ Measurometer.increment_counter('image_vise.params.valid_signatures', 1)
22
22
 
23
23
  # Decode the JSON - only AFTER the signature has been validated,
24
24
  # so we can use symbol keys
@@ -47,7 +47,7 @@ class ImageVise::Pipeline
47
47
  def apply!(magick_image, image_metadata)
48
48
  @ops.each do |operator|
49
49
  operator_short_classname = operator.class.to_s.split('::').pop
50
- ImageVise::Measurometer.instrument('image_vise.op.%s' % operator_short_classname) do
50
+ Measurometer.instrument('image_vise.op.%s' % operator_short_classname) do
51
51
  apply_operator_passing_metadata(magick_image, operator, image_metadata)
52
52
  end
53
53
  end
@@ -13,7 +13,8 @@
13
13
  end
14
14
 
15
15
  DEFAULT_HEADERS = {
16
- 'Allow' => "GET"
16
+ 'Allow' => 'GET',
17
+ 'X-Content-Type-Options' => 'nosniff',
17
18
  }.freeze
18
19
 
19
20
  # Headers for error responses that denote an invalid or
@@ -152,7 +153,7 @@
152
153
 
153
154
  # Download/copy the original into a Tempfile
154
155
  fetcher = ImageVise.fetcher_for(source_image_uri.scheme)
155
- source_file = ImageVise::Measurometer.instrument('image_vise.fetch') do
156
+ source_file = Measurometer.instrument('image_vise.fetch') do
156
157
  fetcher.fetch_uri_to_tempfile(source_image_uri)
157
158
  end
158
159
  file_format = FormatParser.parse(source_file, natures: [:image]).tap { source_file.rewind }
@@ -162,7 +163,7 @@
162
163
  render_destination_file = Tempfile.new('imagevise-render').tap{|f| f.binmode }
163
164
 
164
165
  # Do the actual imaging stuff
165
- expire_after = ImageVise::Measurometer.instrument('image_vise.render_engine.apply_pipeline') do
166
+ expire_after = Measurometer.instrument('image_vise.render_engine.apply_pipeline') do
166
167
  apply_pipeline(source_file.path, pipeline, file_format, render_destination_file.path)
167
168
  end
168
169
 
@@ -295,7 +296,7 @@
295
296
  def apply_pipeline(source_file_path, pipeline, source_format_parser_result, render_to_path)
296
297
 
297
298
  # Load the first frame of the animated GIF _or_ the blended compatibility layer from Photoshop
298
- image_list = ImageVise::Measurometer.instrument('image_vise.load_pixbuf') do
299
+ image_list = Measurometer.instrument('image_vise.load_pixbuf') do
299
300
  Magick::Image.read(source_file_path)
300
301
  end
301
302
 
@@ -312,7 +313,7 @@
312
313
  # it so that we get a KeyError if some operator has deleted it without providing a replacement.
313
314
  # If no operators touched the writer we are going to use the automatic format selection
314
315
  writer = metadata.fetch(:writer, ImageVise::AutoWriter.new)
315
- ImageVise::Measurometer.instrument('image_vise.write_image') do
316
+ Measurometer.instrument('image_vise.write_image') do
316
317
  writer.write_image!(magick_image, metadata, render_to_path)
317
318
  end
318
319
 
@@ -1,3 +1,3 @@
1
1
  class ImageVise
2
- VERSION = '0.6.0'
2
+ VERSION = '0.8.2'
3
3
  end
@@ -110,6 +110,8 @@ describe ImageVise::RenderEngine do
110
110
  expect(last_response.headers['Cache-Control']).to match(/public/)
111
111
 
112
112
  expect(last_response.headers['Content-Type']).to eq('application/json')
113
+ expect(last_response['X-Content-Type-Options']).to eq('nosniff')
114
+
113
115
  parsed = JSON.load(last_response.body)
114
116
  expect(parsed['errors'].to_s).to include("Unfortunate upstream response")
115
117
  end
@@ -182,6 +184,8 @@ describe ImageVise::RenderEngine do
182
184
  expect(last_response.status).to eq(200)
183
185
 
184
186
  expect(last_response.headers['Content-Type']).to eq('image/jpeg')
187
+ expect(last_response['X-Content-Type-Options']).to eq('nosniff')
188
+
185
189
  expect(last_response.headers).to have_key('Content-Length')
186
190
  parsed_image = Magick::Image.from_blob(last_response.body)[0]
187
191
  expect(parsed_image.columns).to eq(10)
@@ -11,6 +11,7 @@ require 'securerandom'
11
11
  require 'addressable/uri'
12
12
  require 'strenv'
13
13
  require 'pry'
14
+ require 'magic_bytes'
14
15
  require_relative 'test_server'
15
16
 
16
17
  TEST_RENDERS_DIR = Dir.mktmpdir
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: image_vise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-04 00:00:00.000000000 Z
11
+ date: 2020-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: patron
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.15'
33
+ version: '3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.15'
40
+ version: '3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: ks
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -76,22 +76,30 @@ dependencies:
76
76
  name: format_parser
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: 0.12.1
82
- - - "<"
79
+ - - "~>"
83
80
  - !ruby/object:Gem::Version
84
- version: '1.0'
81
+ version: '0.25'
85
82
  type: :runtime
86
83
  prerelease: false
87
84
  version_requirements: !ruby/object:Gem::Requirement
88
85
  requirements:
89
- - - ">="
86
+ - - "~>"
90
87
  - !ruby/object:Gem::Version
91
- version: 0.12.1
92
- - - "<"
88
+ version: '0.25'
89
+ - !ruby/object:Gem::Dependency
90
+ name: measurometer
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
93
94
  - !ruby/object:Gem::Version
94
- version: '1.0'
95
+ version: '1'
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1'
95
103
  - !ruby/object:Gem::Dependency
96
104
  name: magic_bytes
97
105
  requirement: !ruby/object:Gem::Requirement
@@ -110,16 +118,16 @@ dependencies:
110
118
  name: bundler
111
119
  requirement: !ruby/object:Gem::Requirement
112
120
  requirements:
113
- - - "~>"
121
+ - - ">="
114
122
  - !ruby/object:Gem::Version
115
- version: '1.7'
123
+ version: '0'
116
124
  type: :development
117
125
  prerelease: false
118
126
  version_requirements: !ruby/object:Gem::Requirement
119
127
  requirements:
120
- - - "~>"
128
+ - - ">="
121
129
  - !ruby/object:Gem::Version
122
- version: '1.7'
130
+ version: '0'
123
131
  - !ruby/object:Gem::Dependency
124
132
  name: rake
125
133
  requirement: !ruby/object:Gem::Requirement
@@ -227,6 +235,7 @@ extra_rdoc_files: []
227
235
  files:
228
236
  - ".gitignore"
229
237
  - ".travis.yml"
238
+ - CHANGELOG.md
230
239
  - DEVELOPMENT.md
231
240
  - Gemfile
232
241
  - LICENSE.txt
@@ -260,7 +269,6 @@ files:
260
269
  - lib/image_vise/version.rb
261
270
  - lib/image_vise/writers/auto_writer.rb
262
271
  - lib/image_vise/writers/jpeg_writer.rb
263
- - lib/measurometer.rb
264
272
  - spec/image_vise/auto_orient_spec.rb
265
273
  - spec/image_vise/background_fill_spec.rb
266
274
  - spec/image_vise/crop_spec.rb
@@ -282,7 +290,6 @@ files:
282
290
  - spec/image_vise/writers/jpeg_writer_spec.rb
283
291
  - spec/image_vise_spec.rb
284
292
  - spec/layers-with-blending.psd
285
- - spec/measurometer_spec.rb
286
293
  - spec/spec_helper.rb
287
294
  - spec/test_server.rb
288
295
  - spec/waterside_magic_hour.jpg
@@ -311,8 +318,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
311
318
  - !ruby/object:Gem::Version
312
319
  version: '0'
313
320
  requirements: []
314
- rubyforge_project:
315
- rubygems_version: 2.5.2
321
+ rubygems_version: 3.1.2
316
322
  signing_key:
317
323
  specification_version: 4
318
324
  summary: Runtime thumbnailing proxy
@@ -1,92 +0,0 @@
1
- # Measurometer is 1-1 API compatible with Appsignal,
2
- # which we use a lot
3
- class ImageVise::Measurometer
4
- class << self
5
- # Permits adding instrumentation drivers. To magically
6
- # obtain all Appsignal instrumentation, add the Appsignal module
7
- # as a driver.
8
- #
9
- # Measurometer.drivers << Appsignal
10
- #
11
- # A driver must be reentrant and thread-safe - it should be possible
12
- # to have multiple `instrument` calls open from different threads at the
13
- # same time.
14
- #
15
- # The driver must support the same interface as the Measurometer class
16
- # itself, minus the `drivers` and `instrument_instance_method` methods.
17
- #
18
- # @return Array
19
- def drivers
20
- @drivers ||= []
21
- @drivers
22
- end
23
-
24
- # Runs a given block within a cascade of `instrument` blocks of all the
25
- # added drivers.
26
- #
27
- # Measurometer.instrument('do_foo') { compute! }
28
- #
29
- # unfolds to
30
- #
31
- # Appsignal.instrument('do_foo') do
32
- # Statsd.timing('do_foo') do
33
- # compute!
34
- # end
35
- # end
36
- #
37
- # Note that it is _imperative_ that the block return value is preserved
38
- # by the drivers and passed as the result of the block.
39
- #
40
- # @param block_name[String] under which path to push the metric
41
- # @param blk[#call] the block to instrument
42
- # @return [Object] the return value of &blk
43
- def instrument(block_name, &blk)
44
- return yield unless @drivers && @drivers.any? # The block wrapping business is not free
45
- @drivers.inject(blk) { |outer_block, driver|
46
- -> {
47
- driver.instrument(block_name, &outer_block)
48
- }
49
- }.call
50
- end
51
-
52
- # Adds a distribution value (sample) under a given path
53
- #
54
- # @param value_path[String] under which path to push the metric
55
- # @param value[Numeric] distribution value
56
- # @return nil
57
- def add_distribution_value(value_path, value)
58
- (@drivers || []).each { |d| d.add_distribution_value(value_path, value) }
59
- nil
60
- end
61
-
62
- # Increment a named counter under a given path
63
- #
64
- # @param counter_path[String] under which path to push the metric
65
- # @param by[Integer] the counter increment to apply
66
- # @return nil
67
- def increment_counter(counter_path, by)
68
- (@drivers || []).each { |d| d.increment_counter(counter_path, by) }
69
- nil
70
- end
71
-
72
- # Wrap an anonymous module around an instance method in the given class to have
73
- # it instrumented automatically. The name of the measurement will be interpolated as:
74
- #
75
- # "#{prefix}.#{rightmost_class_constant_name}.#{instance_method_name}"
76
- #
77
- # @param target_class[Class] the class to instrument
78
- # @param instance_method_name_to_instrument[Symbol] the method name to instrument
79
- # @param path_prefix[String] under which path to push the instrumented metric
80
- # @return void
81
- def instrument_instance_method(target_class, instance_method_name_to_instrument, path_prefix)
82
- short_class_name = target_class.to_s.split('::').last
83
- instrumentation_name = [path_prefix, short_class_name, instance_method_name_to_instrument].join('.')
84
- instrumenter_module = Module.new do
85
- define_method(instance_method_name_to_instrument) do |*any|
86
- ::ImageVise::Measurometer.instrument(instrumentation_name) { super(*any) }
87
- end
88
- end
89
- target_class.prepend(instrumenter_module)
90
- end
91
- end
92
- end
@@ -1,58 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ImageVise::Measurometer do
4
- RSpec::Matchers.define :include_counter_or_measurement_named do |named|
5
- match do |actual|
6
- actual.any? do |e|
7
- e[0] == named && e[1] > 0
8
- end
9
- end
10
- end
11
-
12
- it 'instruments a full cycle FormatParser.parse' do
13
- driver_class = Class.new do
14
- attr_accessor :timings, :counters, :distributions
15
- def initialize
16
- @timings = []
17
- @distributions = []
18
- @counters = []
19
- end
20
-
21
- def instrument(block_name)
22
- s = Process.clock_gettime(Process::CLOCK_MONOTONIC)
23
- yield.tap do
24
- delta = Process.clock_gettime(Process::CLOCK_MONOTONIC) - s
25
- @timings << [block_name, delta * 1000]
26
- end
27
- end
28
-
29
- def add_distribution_value(value_path, value)
30
- @distributions << [value_path, value]
31
- end
32
-
33
- def increment_counter(value_path, value)
34
- @counters << [value_path, value]
35
- end
36
- end
37
-
38
- instrumenter = driver_class.new
39
- described_class.drivers << instrumenter
40
-
41
- builder = ImageVise::Pipeline.new
42
- pipeline = builder.
43
- auto_orient.
44
- fit_crop(width: 48, height: 48, gravity: 'c').
45
- sharpen(radius: 2, sigma: 0.5).
46
- ellipse_stencil.
47
- strip_metadata
48
-
49
- image = Magick::Image.read(test_image_path)[0]
50
- pipeline.apply! image, {}
51
-
52
- described_class.drivers.delete(instrumenter)
53
- expect(described_class.drivers).not_to include(instrumenter)
54
-
55
- expect(instrumenter.timings).to include_counter_or_measurement_named('image_vise.op.AutoOrient')
56
- expect(instrumenter.timings).to include_counter_or_measurement_named('image_vise.op.StripMetadata')
57
- end
58
- end