rack_resize 0.1.0 → 0.1.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 +4 -4
- data/.github/workflows/test.yml +29 -0
- data/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +7 -0
- data/README.md +106 -4
- data/Rakefile +9 -0
- data/config.ru +7 -1
- data/lib/rack_resize/configuration.rb +39 -10
- data/lib/rack_resize/input_parsers/cloudflare.rb +20 -2
- data/lib/rack_resize/processing.rb +11 -11
- data/lib/rack_resize/processors/imlib2.rb +0 -1
- data/lib/rack_resize/processors/mini_magick.rb +0 -6
- data/lib/rack_resize/processors/sips.rb +30 -26
- data/lib/rack_resize/processors/vips.rb +0 -2
- data/lib/rack_resize/rack_app.rb +29 -27
- data/lib/rack_resize/rails_autoload.rb +1 -1
- data/lib/rack_resize.rb +5 -1
- data/rack_resize.gemspec +2 -2
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 48043ad5846a54c36958ce1d2b4648de14b01c30db46ec8dcdb2b601628118f2
|
|
4
|
+
data.tar.gz: 2ccd0c5703c104cb952bd4e299fc6e1be49ef2e08849f2a9637d661adca13a22
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9fa7b2853a0701bf476f9730d1aae31ffc9edb28f53d032e8d51acb3c7e82fdd07e64e2225d4195507bfde69956b44bc48152d9d4b1c4e2fa840fe140d592518
|
|
7
|
+
data.tar.gz: e0b76b4d16323c0a87bae2d8c61fa2d44d0a72d1d27c6d8872bd091084ab2a5f9055216a48af9724af5ccff8dba6cf782acf8f7a38ca0216039318a87268c479
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
ruby: ['3.3', '3.4', '4.0']
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Install package
|
|
20
|
+
run: |
|
|
21
|
+
sudo apt-get update
|
|
22
|
+
sudo apt-get install -y libvips42 imagemagick libimlib2 libimlib2-dev
|
|
23
|
+
|
|
24
|
+
- uses: ruby/setup-ruby@v1
|
|
25
|
+
with:
|
|
26
|
+
ruby-version: ${{ matrix.ruby }}
|
|
27
|
+
bundler-cache: true
|
|
28
|
+
|
|
29
|
+
- run: bundle exec rake test
|
data/.gitignore
CHANGED
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.0.5
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,6 +1,108 @@
|
|
|
1
|
+
[](https://badge.fury.io/rb/rack_resize)
|
|
1
2
|
|
|
2
|
-
|
|
3
|
-
RESIZE IMAGE sips samples/big.jpg - {:width=>"150"} - 0.121s
|
|
4
|
-
RESIZE IMAGE vips samples/big.jpg - {:width=>"150"} - 0.116s
|
|
3
|
+
Designed to be local simulation of CDN's resize feature
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
How to use with Rails
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
group :development do
|
|
9
|
+
gem "rack_resize", require: "rack_resize/rails_autoload"
|
|
10
|
+
end
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
How to use with Rack
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
use RackResize::RackApp, processor: :imlib2, assets_folder: "samples"
|
|
17
|
+
use Rack::Static, urls: [""], root: "samples", index: "index.html" # optional
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### URL Formats:
|
|
21
|
+
|
|
22
|
+
Cloudflare format: (can be used with helpers from `carrierwave-cloudflare` gem)
|
|
23
|
+
```
|
|
24
|
+
/cdn-cgi/image/width=426,format=auto/assets/pets/dog.jpg
|
|
25
|
+
```
|
|
26
|
+
Fastly and bunny.net: (tbd)
|
|
27
|
+
```
|
|
28
|
+
/assets/pets/dog.jpg?width=300
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Configuration:
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
RackResize.configure do |config|
|
|
35
|
+
config.assets_folders = { "assets" => Rails.root.join('app', 'assets', 'images') }
|
|
36
|
+
config.processor = :sips / :vips / :mini_magick / :imlib2
|
|
37
|
+
config.default_quality = 95
|
|
38
|
+
config.save_resized = false
|
|
39
|
+
config.cache_folder = Rails.root.join('tmp', 'rack_resize_cache') # used if save_resized enabled
|
|
40
|
+
config.http_cache_max_age = 86400
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Supported Processing Backends:
|
|
45
|
+
|
|
46
|
+
<table>
|
|
47
|
+
<tr>
|
|
48
|
+
<th>libaray</th>
|
|
49
|
+
<th>dependency</th>
|
|
50
|
+
<th>config</th>
|
|
51
|
+
</tr>
|
|
52
|
+
<tr>
|
|
53
|
+
<td>mini_magick</td>
|
|
54
|
+
<td>
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
gem "image_processing"
|
|
58
|
+
gem "mini_magick"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
</td>
|
|
62
|
+
<td>
|
|
63
|
+
|
|
64
|
+
`processor: :mini_magick`
|
|
65
|
+
|
|
66
|
+
</td>
|
|
67
|
+
</tr>
|
|
68
|
+
<tr>
|
|
69
|
+
<td>vips</td>
|
|
70
|
+
<td>
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
gem "image_processing"
|
|
74
|
+
gem "ruby-vips"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
</td>
|
|
78
|
+
<td>
|
|
79
|
+
|
|
80
|
+
`processor: :vips`
|
|
81
|
+
|
|
82
|
+
</td>
|
|
83
|
+
</tr>
|
|
84
|
+
<tr>
|
|
85
|
+
<td>sips (MacOS only)</td>
|
|
86
|
+
<td>none</td>
|
|
87
|
+
<td>
|
|
88
|
+
|
|
89
|
+
`processor: :sips`
|
|
90
|
+
|
|
91
|
+
</td>
|
|
92
|
+
</tr>
|
|
93
|
+
<tr>
|
|
94
|
+
<td>imlib2</td>
|
|
95
|
+
<td>
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
gem "rszr"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
</td>
|
|
102
|
+
<td>
|
|
103
|
+
|
|
104
|
+
`processor: :imlib2`
|
|
105
|
+
|
|
106
|
+
</td>
|
|
107
|
+
</tr>
|
|
108
|
+
</table>
|
data/Rakefile
ADDED
data/config.ru
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
#
|
|
2
|
+
# usage:
|
|
3
|
+
# gem install rackup
|
|
4
|
+
# rackup
|
|
5
|
+
#
|
|
6
|
+
|
|
1
7
|
require_relative "lib/rack_resize"
|
|
2
8
|
require "rack/static"
|
|
3
9
|
|
|
4
|
-
use RackResize::RackApp, processor: :imlib2, assets_folder: "samples"
|
|
10
|
+
use RackResize::RackApp, processor: :imlib2, assets_folder: "samples"
|
|
5
11
|
|
|
6
12
|
use Rack::Static, urls: [""], root: "samples", index: "index.html"
|
|
7
13
|
|
|
@@ -3,21 +3,33 @@ require 'pathname'
|
|
|
3
3
|
class RackResize::Configuration
|
|
4
4
|
PROCESSORS = %i[sips vips mini_magick imlib2].freeze
|
|
5
5
|
|
|
6
|
-
attr_reader :processor
|
|
7
|
-
attr_accessor :save_resized, :default_quality, :cache_folder, :
|
|
6
|
+
attr_reader :processor, :assets_folders
|
|
7
|
+
attr_accessor :save_resized, :default_quality, :cache_folder, :http_cache_max_age, :max_dimension, :logger
|
|
8
8
|
|
|
9
9
|
alias_method :save_resized?, :save_resized
|
|
10
10
|
|
|
11
11
|
def initialize(options = {})
|
|
12
|
-
@processor
|
|
13
|
-
@save_resized
|
|
14
|
-
@default_quality
|
|
15
|
-
@cache_folder
|
|
16
|
-
@
|
|
12
|
+
@processor = options[:processor] || RUBY_PLATFORM.include?('darwin') ? :sips : :mini_magick
|
|
13
|
+
@save_resized = options.key?(:save_resized) ? options[:save_resized] : false
|
|
14
|
+
@default_quality = options[:default_quality] || 95
|
|
15
|
+
@cache_folder = options[:cache_folder]
|
|
16
|
+
@http_cache_max_age = options[:http_cache_max_age] || 86400 # 1 day
|
|
17
|
+
@max_dimension = options[:max_dimension] || 4000
|
|
18
|
+
@logger = options[:logger]
|
|
17
19
|
|
|
18
|
-
if
|
|
20
|
+
self.assets_folders = options[:assets_folders] if options[:assets_folders]
|
|
21
|
+
|
|
22
|
+
if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
|
|
19
23
|
@cache_folder ||= Rails.root.join('tmp', 'rack_resize_cache')
|
|
20
|
-
|
|
24
|
+
unless options.key?(:assets_folders)
|
|
25
|
+
self.assets_folders = {
|
|
26
|
+
"assets" => Rails.root.join("app/assets/images"),
|
|
27
|
+
"uploads" => Rails.root.join("public/uploads"),
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
unless options.key?(:save_resized)
|
|
31
|
+
@save_resized = true
|
|
32
|
+
end
|
|
21
33
|
end
|
|
22
34
|
|
|
23
35
|
if options[:processor]
|
|
@@ -25,6 +37,17 @@ class RackResize::Configuration
|
|
|
25
37
|
end
|
|
26
38
|
end
|
|
27
39
|
|
|
40
|
+
def assets_folders=(values)
|
|
41
|
+
if values.is_a?(Array)
|
|
42
|
+
@assets_folders = values.map { |v| [format_asset_path(v), Pathname.new(v)] }.to_h
|
|
43
|
+
elsif values.is_a?(Hash)
|
|
44
|
+
@assets_folders = values.transform_values { |v| v.is_a?(Pathname) ? v : Pathname.new(v) }
|
|
45
|
+
.transform_keys {|k| format_asset_path(k) }
|
|
46
|
+
else
|
|
47
|
+
raise ArgumentError, "RackResize::Configuration.assets_folders can be either hash or array, received #{values.class}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
28
51
|
def processor=(value)
|
|
29
52
|
value = value.to_sym
|
|
30
53
|
unless PROCESSORS.include?(value)
|
|
@@ -36,7 +59,7 @@ class RackResize::Configuration
|
|
|
36
59
|
|
|
37
60
|
def processor_instance
|
|
38
61
|
@processor_instance ||= case @processor
|
|
39
|
-
when :mini_magick then RackResize::MiniMagick.new
|
|
62
|
+
when :mini_magick then RackResize::Processors::MiniMagick.new
|
|
40
63
|
when :vips then RackResize::Processors::Vips.new
|
|
41
64
|
when :sips then RackResize::Processors::Sips.new
|
|
42
65
|
when :imlib2 then RackResize::Processors::Imlib2.new
|
|
@@ -44,4 +67,10 @@ class RackResize::Configuration
|
|
|
44
67
|
raise "RackResize - Unknow image processor #{@processor.inspect}"
|
|
45
68
|
end
|
|
46
69
|
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def format_asset_path(path)
|
|
74
|
+
path.start_with?('/') ? path.to_s : "/#{path}"
|
|
75
|
+
end
|
|
47
76
|
end
|
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
module RackResize::InputParsers::Cloudflare
|
|
2
|
+
extend self
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
# process string like this
|
|
5
|
+
# /cdn-cgi/image/width=426,format=auto/assets/templates/vancouver-27c47f55.jpg
|
|
6
|
+
|
|
7
|
+
def parse_input(fullpath, cf_path_prefix:)
|
|
8
|
+
unless fullpath.start_with?(cf_path_prefix)
|
|
9
|
+
return { route_matched: false, req_params: nil, asset_path: nil }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
fullpath = fullpath.delete_prefix("/cdn-cgi").delete_prefix("/image").delete_prefix("/")
|
|
13
|
+
file_path_match = fullpath.match(%r{(?<params>[^\/]+)(?<file>\/.+?)(-[\da-f]{8})?(?<ext>\.\w{2,})$})
|
|
14
|
+
|
|
15
|
+
return { route_matched: true, req_params: nil, asset_path: nil } unless file_path_match
|
|
16
|
+
|
|
17
|
+
req_params = file_path_match[:params].split(",").map {|s| s.split("=") }.to_h.transform_keys(&:to_sym)
|
|
18
|
+
asset_path = "#{file_path_match[:file]}#{file_path_match[:ext]}"
|
|
19
|
+
|
|
20
|
+
{ route_matched: true, req_params:, asset_path: }
|
|
21
|
+
end
|
|
4
22
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'digest'
|
|
2
|
+
|
|
1
3
|
class RackResize::Processing
|
|
2
4
|
attr_reader :config
|
|
3
5
|
|
|
@@ -24,8 +26,11 @@ class RackResize::Processing
|
|
|
24
26
|
|
|
25
27
|
def process_file(source_file:, req_params:, target_file: nil)
|
|
26
28
|
dpr = req_params[:dpr]&.to_f || 1.0
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
dpr = [[dpr, 0.1].max, 10.0].min
|
|
30
|
+
|
|
31
|
+
max = config.max_dimension.to_f
|
|
32
|
+
target_width = (req_params[:w]&.to_i || req_params[:width]&.to_i)&.*(dpr)&.clamp(1, max)
|
|
33
|
+
target_height = (req_params[:h]&.to_i || req_params[:height]&.to_i)&.*(dpr)&.clamp(1, max)
|
|
29
34
|
|
|
30
35
|
start_time = Time.now
|
|
31
36
|
begin
|
|
@@ -37,13 +42,8 @@ class RackResize::Processing
|
|
|
37
42
|
end
|
|
38
43
|
|
|
39
44
|
def logger
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
else
|
|
44
|
-
require 'logger'
|
|
45
|
-
Logger.new(STDOUT)
|
|
46
|
-
end
|
|
47
|
-
end
|
|
45
|
+
config.logger ||
|
|
46
|
+
(defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger) ||
|
|
47
|
+
(require('logger') && Logger.new(STDOUT))
|
|
48
48
|
end
|
|
49
|
-
end
|
|
49
|
+
end
|
|
@@ -11,7 +11,6 @@ class RackResize::Processors::Imlib2
|
|
|
11
11
|
image.resize!(target_width || :auto, target_height || :auto) if target_width || target_height
|
|
12
12
|
|
|
13
13
|
if target_file
|
|
14
|
-
image.call(destination: target_file)
|
|
15
14
|
image.save(target_file)
|
|
16
15
|
else
|
|
17
16
|
image.save_data(format: source_file.to_s =~ /\.png$/ ? :png : :jpeg)
|
|
@@ -45,9 +45,3 @@ class RackResize::Processors::MiniMagick
|
|
|
45
45
|
image&.destroy!
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
|
-
|
|
49
|
-
# magick /Users/pavel/Work/resume-io/app/assets/images/templates/vancouver.jpg -auto-orient -resize 426.0x> -quality 95 /Users/pavel/Work/resume-io/tmp/cdn_cgi_cache/60f2727cce350874040b321219f05766.jpg
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
# magick mogrify -resize 426.0x> /var/folders/n9/b__lxh7j1_xcwg4k_8j2_39m0000gp/T/mini_magick20260709-58478-qowydk.jpg
|
|
53
|
-
# magick mogrify -quality 95 /var/folders/n9/b__lxh7j1_xcwg4k_8j2_39m0000gp/T/mini_magick20260709-58478-qowydk.jpg
|
|
@@ -1,37 +1,41 @@
|
|
|
1
|
-
require "
|
|
1
|
+
require "open3"
|
|
2
2
|
|
|
3
3
|
class RackResize::Processors::Sips
|
|
4
4
|
|
|
5
5
|
def resize(source_file:, target_width:, target_height:, target_file: nil)
|
|
6
|
-
|
|
7
|
-
args
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
args = %w[sips --deleteColorManagementProperties]
|
|
7
|
+
args += ["-s", "formatOptions", RackResize.config.default_quality.to_s]
|
|
8
|
+
|
|
9
|
+
if target_width && target_height
|
|
10
|
+
info, status = Open3.capture2("sips", "-g", "pixelWidth", "-g", "pixelHeight", source_file.to_s)
|
|
11
|
+
raise "sips failed to read dimensions for #{source_file}" unless status.success?
|
|
12
|
+
src_w = info[/pixelWidth: (\d+)/, 1]&.to_f
|
|
13
|
+
src_h = info[/pixelHeight: (\d+)/, 1]&.to_f
|
|
14
|
+
if src_w && src_h && (target_width.to_f / src_w) <= (target_height.to_f / src_h)
|
|
15
|
+
args += ["--resampleWidth", target_width.to_i.to_s]
|
|
16
|
+
else
|
|
17
|
+
args += ["--resampleHeight", target_height.to_i.to_s]
|
|
18
|
+
end
|
|
14
19
|
else
|
|
15
|
-
|
|
16
|
-
args
|
|
20
|
+
args += ["--resampleWidth", target_width.to_i.to_s] if target_width
|
|
21
|
+
args += ["--resampleHeight", target_height.to_i.to_s] if target_height
|
|
17
22
|
end
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
result = `#{args.join(" ")}`
|
|
24
|
-
|
|
25
|
-
puts "sips command result: #{result}"
|
|
26
|
-
|
|
27
|
-
unless target_file
|
|
28
|
-
begin
|
|
29
|
-
return File.open(tmp_file.path, 'rb', &:read)
|
|
30
|
-
ensure
|
|
31
|
-
tmp_file.unlink
|
|
32
|
-
end
|
|
24
|
+
if target_file
|
|
25
|
+
_, status = Open3.capture2(*args, "-o", target_file.to_s, source_file.to_s)
|
|
26
|
+
raise "sips failed (exit #{status.exitstatus}) for #{source_file}" unless status.success?
|
|
27
|
+
return nil
|
|
33
28
|
end
|
|
34
29
|
|
|
35
|
-
|
|
30
|
+
tmp = Tempfile.new(["result", File.extname(source_file)])
|
|
31
|
+
tmp_path = tmp.path || raise("tempfile has no path")
|
|
32
|
+
begin
|
|
33
|
+
_, status = Open3.capture2(*args, "-o", tmp_path, source_file.to_s)
|
|
34
|
+
raise "sips failed (exit #{status.exitstatus}) for #{source_file}" unless status.success?
|
|
35
|
+
File.binread(tmp_path)
|
|
36
|
+
ensure
|
|
37
|
+
tmp.close
|
|
38
|
+
tmp.unlink
|
|
39
|
+
end
|
|
36
40
|
end
|
|
37
41
|
end
|
|
@@ -11,8 +11,6 @@ class RackResize::Processors::Vips
|
|
|
11
11
|
image = image.resize_to_limit(target_width, target_height) if target_width || target_height
|
|
12
12
|
image = image.saver(quality: RackResize.config.default_quality)
|
|
13
13
|
|
|
14
|
-
# image.call(destination: target_file)
|
|
15
|
-
|
|
16
14
|
if target_file
|
|
17
15
|
image.call(destination: target_file)
|
|
18
16
|
else
|
data/lib/rack_resize/rack_app.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
1
|
require 'rack'
|
|
4
2
|
|
|
5
3
|
class RackResize::RackApp
|
|
@@ -13,40 +11,45 @@ class RackResize::RackApp
|
|
|
13
11
|
|
|
14
12
|
@config = options == {} ? RackResize.config : RackResize::Configuration.new(options)
|
|
15
13
|
@processing = RackResize::Processing.new(config: @config)
|
|
16
|
-
@
|
|
14
|
+
@cf_path_prefix = options[:cf_path_prefix] || "/cdn-cgi/image"
|
|
17
15
|
end
|
|
18
16
|
|
|
19
17
|
def call(env)
|
|
20
|
-
# process string like this
|
|
21
|
-
# /cdn-cgi/image/width=426,format=auto/assets/templates/vancouver-27c47f55.jpg
|
|
22
|
-
|
|
23
18
|
request = Rack::Request.new(env)
|
|
24
19
|
fullpath = request.path_info
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
end
|
|
21
|
+
RackResize::InputParsers::Cloudflare.parse_input(fullpath, cf_path_prefix: @cf_path_prefix) =>
|
|
22
|
+
{route_matched:, req_params:, asset_path:}
|
|
29
23
|
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
return @app.call(env) unless route_matched
|
|
25
|
+
return error_resp("can't parse file path") unless asset_path
|
|
32
26
|
|
|
33
|
-
return error_resp("
|
|
27
|
+
return error_resp("no assets folders configured") if config.assets_folders.nil? || config.assets_folders.empty?
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
has_matched = false
|
|
30
|
+
asset_file = nil
|
|
31
|
+
config.assets_folders.each do |prefix, folder|
|
|
32
|
+
if asset_path.start_with?(prefix)
|
|
33
|
+
asset_file = folder.join(asset_path.delete_prefix(prefix + (prefix.end_with?("/") ? "" : "/")))
|
|
34
|
+
if asset_file.expand_path.to_s.start_with?(folder.to_s)
|
|
35
|
+
has_matched = true
|
|
36
|
+
end
|
|
37
|
+
break
|
|
38
|
+
end
|
|
42
39
|
end
|
|
43
40
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
if asset_path.include?("..")
|
|
42
|
+
@processing.logger.info("RackResize::RackApp - File path has invalid byte sequence #{asset_path}")
|
|
43
|
+
return error_resp(".. is not allowed in image path")
|
|
44
|
+
end
|
|
45
|
+
unless has_matched
|
|
46
|
+
@processing.logger.info("RackResize::RackApp - requested file #{asset_path} not match any of configured assets folder #{config.assets_folders.keys}")
|
|
47
|
+
return error_resp("invalid file path")
|
|
48
|
+
end
|
|
49
|
+
unless asset_file.exist?
|
|
50
|
+
@processing.logger.info("RackResize::RackApp - File path fond #{asset_path} => #{asset_file}")
|
|
51
|
+
return error_resp("file not exists on a server")
|
|
52
|
+
end
|
|
50
53
|
|
|
51
54
|
file_content = @processing.process!(source_file: asset_file, req_params:)
|
|
52
55
|
return send_file(asset_file:, file_content:)
|
|
@@ -58,7 +61,6 @@ class RackResize::RackApp
|
|
|
58
61
|
|
|
59
62
|
def send_file(asset_file:, file_content: nil)
|
|
60
63
|
content_type = Rack::Mime.mime_type(File.extname(asset_file), "application/octet-stream")
|
|
61
|
-
# file = file_path ? File.open(file_path, "rb") : StringIO.new(file_content)
|
|
62
64
|
|
|
63
65
|
[
|
|
64
66
|
200,
|
|
@@ -66,7 +68,7 @@ class RackResize::RackApp
|
|
|
66
68
|
"content-type" => content_type,
|
|
67
69
|
"content-length" => file_content.size.to_s,
|
|
68
70
|
"content-disposition" => "inline",
|
|
69
|
-
"cache-control" => "max-age
|
|
71
|
+
"cache-control" => "max-age=#{config.http_cache_max_age}" # 1 day
|
|
70
72
|
},
|
|
71
73
|
file_content
|
|
72
74
|
]
|
data/lib/rack_resize.rb
CHANGED
|
@@ -7,10 +7,14 @@ module RackResize
|
|
|
7
7
|
module Processors
|
|
8
8
|
autoload :Sips, "#{__dir__}/rack_resize/processors/sips"
|
|
9
9
|
autoload :Vips, "#{__dir__}/rack_resize/processors/vips"
|
|
10
|
-
autoload :
|
|
10
|
+
autoload :MiniMagick, "#{__dir__}/rack_resize/processors/mini_magick"
|
|
11
11
|
autoload :Imlib2, "#{__dir__}/rack_resize/processors/imlib2"
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
+
module InputParsers
|
|
15
|
+
autoload :Cloudflare, "#{__dir__}/rack_resize/input_parsers/cloudflare"
|
|
16
|
+
end
|
|
17
|
+
|
|
14
18
|
class << self
|
|
15
19
|
def configuration
|
|
16
20
|
@configuration ||= Configuration.new
|
data/rack_resize.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = "rack_resize"
|
|
3
|
-
s.version = "0.1.
|
|
3
|
+
s.version = "0.1.2"
|
|
4
4
|
s.author = ["Pavel Evstigneev"]
|
|
5
5
|
s.email = ["pavel.evst@gmail.com"]
|
|
6
6
|
s.homepage = "https://github.com/paxa/rack_resize"
|
|
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
|
8
8
|
s.license = 'MIT'
|
|
9
9
|
s.required_ruby_version = ['>= 3.0']
|
|
10
10
|
|
|
11
|
-
s.files = `git ls-files`.split("\n")
|
|
11
|
+
s.files = `git ls-files`.split("\n").delete_if{|f| f.start_with?('samples', 'test') }
|
|
12
12
|
s.test_files = []
|
|
13
13
|
|
|
14
14
|
s.require_paths = ["lib"]
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rack_resize
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Pavel Evstigneev
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rack
|
|
@@ -35,9 +35,12 @@ executables: []
|
|
|
35
35
|
extensions: []
|
|
36
36
|
extra_rdoc_files: []
|
|
37
37
|
files:
|
|
38
|
+
- ".github/workflows/test.yml"
|
|
38
39
|
- ".gitignore"
|
|
40
|
+
- ".ruby-version"
|
|
39
41
|
- Gemfile
|
|
40
42
|
- README.md
|
|
43
|
+
- Rakefile
|
|
41
44
|
- config.ru
|
|
42
45
|
- lib/rack_resize.rb
|
|
43
46
|
- lib/rack_resize/configuration.rb
|
|
@@ -68,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
68
71
|
- !ruby/object:Gem::Version
|
|
69
72
|
version: '0'
|
|
70
73
|
requirements: []
|
|
71
|
-
rubygems_version:
|
|
74
|
+
rubygems_version: 4.0.10
|
|
72
75
|
specification_version: 4
|
|
73
76
|
summary: Image resizing on a fly
|
|
74
77
|
test_files: []
|