image_size 3.0.1 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/check.yml +3 -9
- data/.github/workflows/rubocop.yml +16 -0
- data/.rubocop.yml +6 -0
- data/.rubocop_todo.yml +3 -3
- data/CHANGELOG.markdown +10 -0
- data/README.markdown +53 -3
- data/image_size.gemspec +3 -3
- data/lib/image_size/uri_reader.rb +82 -44
- data/lib/image_size.rb +1 -0
- data/spec/image_size/chunky_reader_spec.rb +5 -3
- data/spec/image_size_spec.rb +73 -22
- data/spec/images/empty +0 -0
- data/spec/test_server.rb +61 -0
- metadata +11 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0873a78a9fb9f84f07d0389071379dda288330bd38ee7516b442ffde85a3af8
|
4
|
+
data.tar.gz: 0b9fffd2311efa1c24379686821289951a4cd2ec895c27325148a886a24ff57b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6dede99002af9b9fc32f9776e42019079abcd846370c06b2aeee812a73c9ec46dcb6c703d1ae454f807d532c1d6b740aabb999892a6ef610cd17311f6a9a7f0
|
7
|
+
data.tar.gz: 819d8a3b7797b1f12b59eb608ffdeda9338314a923ca54711143832685853ed36b9ae8d165fcfa242ce4e1d72aecd5a03bd11714aa7aee3b464722ea8bb4688f
|
data/.github/workflows/check.yml
CHANGED
@@ -19,8 +19,10 @@ jobs:
|
|
19
19
|
- '2.6'
|
20
20
|
- '2.7'
|
21
21
|
- '3.0'
|
22
|
+
- '3.1'
|
22
23
|
- jruby-9.1
|
23
24
|
- jruby-9.2
|
25
|
+
- jruby-9.3
|
24
26
|
fail-fast: false
|
25
27
|
steps:
|
26
28
|
- uses: actions/checkout@v2
|
@@ -50,6 +52,7 @@ jobs:
|
|
50
52
|
- '2.6'
|
51
53
|
- '2.7'
|
52
54
|
- '3.0'
|
55
|
+
- '3.1'
|
53
56
|
fail-fast: false
|
54
57
|
steps:
|
55
58
|
- uses: actions/checkout@v2
|
@@ -58,12 +61,3 @@ jobs:
|
|
58
61
|
ruby-version: "${{ matrix.ruby }}"
|
59
62
|
bundler-cache: true
|
60
63
|
- run: bundle exec rspec --format documentation
|
61
|
-
rubocop:
|
62
|
-
runs-on: ubuntu-latest
|
63
|
-
steps:
|
64
|
-
- uses: actions/checkout@v2
|
65
|
-
- uses: ruby/setup-ruby@v1
|
66
|
-
with:
|
67
|
-
ruby-version: '3.0'
|
68
|
-
bundler-cache: true
|
69
|
-
- run: bundle exec rubocop
|
@@ -0,0 +1,16 @@
|
|
1
|
+
name: rubocop
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
pull_request:
|
5
|
+
schedule:
|
6
|
+
- cron: 45 4 * * 3
|
7
|
+
jobs:
|
8
|
+
rubocop:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
steps:
|
11
|
+
- uses: actions/checkout@v2
|
12
|
+
- uses: ruby/setup-ruby@v1
|
13
|
+
with:
|
14
|
+
ruby-version: '3.1'
|
15
|
+
bundler-cache: true
|
16
|
+
- run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
@@ -53,6 +53,9 @@ Style/EmptyCaseCondition:
|
|
53
53
|
Style/Encoding:
|
54
54
|
Enabled: false
|
55
55
|
|
56
|
+
Style/FileRead:
|
57
|
+
Enabled: false
|
58
|
+
|
56
59
|
Style/HashEachMethods:
|
57
60
|
Enabled: true
|
58
61
|
|
@@ -77,6 +80,9 @@ Style/ParallelAssignment:
|
|
77
80
|
Style/SafeNavigation:
|
78
81
|
Enabled: false
|
79
82
|
|
83
|
+
Style/SlicingWithRange:
|
84
|
+
Enabled: false
|
85
|
+
|
80
86
|
Style/TrailingCommaInArrayLiteral:
|
81
87
|
EnforcedStyleForMultiline: comma
|
82
88
|
|
data/.rubocop_todo.yml
CHANGED
@@ -9,17 +9,17 @@
|
|
9
9
|
# Offense count: 8
|
10
10
|
# Configuration parameters: IgnoredMethods.
|
11
11
|
Metrics/AbcSize:
|
12
|
-
|
12
|
+
Enabled: false
|
13
13
|
|
14
14
|
# Offense count: 5
|
15
15
|
# Configuration parameters: IgnoredMethods.
|
16
16
|
Metrics/CyclomaticComplexity:
|
17
|
-
|
17
|
+
Enabled: false
|
18
18
|
|
19
19
|
# Offense count: 2
|
20
20
|
# Configuration parameters: IgnoredMethods.
|
21
21
|
Metrics/PerceivedComplexity:
|
22
|
-
|
22
|
+
Enabled: false
|
23
23
|
|
24
24
|
# Offense count: 8
|
25
25
|
# Cop supports --auto-correct.
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v3.1.0 (2022-09-17)
|
6
|
+
|
7
|
+
* Document experimental fetching from http server [#18](https://github.com/toy/image_size/issues/18) [@toy](https://github.com/toy)
|
8
|
+
* Improve experimental fetching of image meta from http server by reading only required amount of data when server does not support range header [@toy](https://github.com/toy)
|
9
|
+
|
10
|
+
## v3.0.2 (2022-05-19)
|
11
|
+
|
12
|
+
* Fix handling empty files [#20](https://github.com/toy/image_size/issues/20) [@toy](https://github.com/toy)
|
13
|
+
|
5
14
|
## v3.0.1 (2021-10-21)
|
6
15
|
|
7
16
|
* Fix reading file chunks starting after EOF and reading chunks non-consecutively [toy/image_optim_rails#12](https://github.com/toy/image_optim_rails/issues/12) [@toy](https://github.com/toy)
|
@@ -11,6 +20,7 @@
|
|
11
20
|
* Read only required chunks of data for files and seekable IOs [@toy](https://github.com/toy)
|
12
21
|
* Raise `FormatError` whenever reading data returns less data than expected [#12](https://github.com/toy/image_size/issues/12) [@toy](https://github.com/toy)
|
13
22
|
* Add `w`/`width` and `h`/`height` accessors to `Size` [@toy](https://github.com/toy)
|
23
|
+
* Experimental efficient fetching of image meta from http server supporting range [@toy](https://github.com/toy)
|
14
24
|
|
15
25
|
## v2.1.2 (2021-08-21)
|
16
26
|
|
data/README.markdown
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
[![Gem Version](https://img.shields.io/gem/v/image_size?logo=rubygems)](https://rubygems.org/gems/image_size)
|
2
2
|
[![Build Status](https://img.shields.io/github/workflow/status/toy/image_size/check/master?logo=github)](https://github.com/toy/image_size/actions/workflows/check.yml)
|
3
|
+
[![Rubocop](https://img.shields.io/github/workflow/status/toy/image_size/rubocop/master?label=rubocop&logo=rubocop)](https://github.com/toy/image_size/actions/workflows/rubocop.yml)
|
3
4
|
|
4
5
|
# image_size
|
5
6
|
|
@@ -17,7 +18,7 @@ gem install image_size
|
|
17
18
|
Add to your `Gemfile`:
|
18
19
|
|
19
20
|
```ruby
|
20
|
-
gem 'image_size', '~>
|
21
|
+
gem 'image_size', '~> 3.0'
|
21
22
|
```
|
22
23
|
|
23
24
|
## Usage
|
@@ -53,7 +54,7 @@ require 'image_size'
|
|
53
54
|
image_size = ImageSize.new(ARGF)
|
54
55
|
```
|
55
56
|
|
56
|
-
Works with `open-uri
|
57
|
+
Works with `open-uri`, see [experimental HTTP server interface below](#experimental-fetch-image-meta-from-http-server):
|
57
58
|
|
58
59
|
```ruby
|
59
60
|
require 'image_size'
|
@@ -89,9 +90,58 @@ File.open('spec/images/jpeg/436x429.jpeg', 'rb') do |fh|
|
|
89
90
|
end
|
90
91
|
```
|
91
92
|
|
93
|
+
### Experimental: fetch image meta from HTTP server
|
94
|
+
|
95
|
+
If server recognises Range header, only needed chunks will be fetched even for TIFF images, otherwise required amount
|
96
|
+
of data will be fetched, in most cases first few kilobytes (TIFF images is an exception).
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
require 'image_size'
|
100
|
+
require 'image_size/uri_reader'
|
101
|
+
|
102
|
+
url = 'http://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_1350660_1350692_33_images.jpg'
|
103
|
+
p ImageSize.url(url).size
|
104
|
+
```
|
105
|
+
|
106
|
+
This interface is as fast as dedicated gem fastimage for images with meta information in the header:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
url = 'http://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_1350660_1350692_33_images.jpg'
|
110
|
+
puts Benchmark.measure{ p FastImage.size(url) }
|
111
|
+
```
|
112
|
+
```
|
113
|
+
[9545, 6623]
|
114
|
+
0.004176 0.001974 0.006150 ( 0.282889)
|
115
|
+
```
|
116
|
+
```ruby
|
117
|
+
puts Benchmark.measure{ p ImageSize.url(url).size }
|
118
|
+
```
|
119
|
+
```
|
120
|
+
[9545, 6623]
|
121
|
+
0.005604 0.001406 0.007010 ( 0.238629)
|
122
|
+
```
|
123
|
+
|
124
|
+
And considerably faster for images with meta information at the end of file:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
url = "https://upload.wikimedia.org/wikipedia/commons/c/c7/Curiosity%27s_Vehicle_System_Test_Bed_%28VSTB%29_Rover_%28PIA15876%29.tif"
|
128
|
+
puts Benchmark.measure{ p FastImage.size(url) }
|
129
|
+
```
|
130
|
+
```
|
131
|
+
[7360, 4912]
|
132
|
+
0.331284 0.247295 0.578579 ( 6.027051)
|
133
|
+
```
|
134
|
+
```ruby
|
135
|
+
puts Benchmark.measure{ p ImageSize.url(url).size }
|
136
|
+
```
|
137
|
+
```
|
138
|
+
[7360, 4912]
|
139
|
+
0.006247 0.001045 0.007292 ( 0.197631)
|
140
|
+
```
|
141
|
+
|
92
142
|
## Licence
|
93
143
|
|
94
144
|
This code is free to use under the terms of the [Ruby's licence](LICENSE.txt).
|
95
145
|
|
96
146
|
Original author: Keisuke Minami <keisuke@rccn.com>.\
|
97
|
-
Further development 2010-
|
147
|
+
Further development 2010-2022 Ivan Kuchin https://github.com/toy/image_size
|
data/image_size.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'image_size'
|
5
|
-
s.version = '3.0
|
5
|
+
s.version = '3.1.0'
|
6
6
|
s.summary = %q{Measure image size using pure Ruby}
|
7
7
|
s.description = %q{Measure following file dimensions: apng, bmp, cur, gif, ico, j2c, jp2, jpeg, jpx, mng, pam, pbm, pcx, pgm, png, ppm, psd, svg, swf, tiff, webp, xbm, xpm}
|
8
8
|
s.homepage = "https://github.com/toy/#{s.name}"
|
@@ -22,8 +22,8 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.require_paths = %w[lib]
|
23
23
|
|
24
24
|
s.add_development_dependency 'rspec', '~> 3.0'
|
25
|
-
if RUBY_VERSION >= '2.
|
26
|
-
s.add_development_dependency 'rubocop', '~> 1.
|
25
|
+
if RUBY_VERSION >= '2.5'
|
26
|
+
s.add_development_dependency 'rubocop', '~> 1.22'
|
27
27
|
s.add_development_dependency 'rubocop-rspec', '~> 2.0'
|
28
28
|
end
|
29
29
|
end
|
@@ -6,65 +6,103 @@ require 'image_size/chunky_reader'
|
|
6
6
|
require 'net/https'
|
7
7
|
require 'uri'
|
8
8
|
|
9
|
-
#
|
9
|
+
# Experimental, not yet part of stable API
|
10
10
|
#
|
11
|
-
# It adds ability to fetch
|
12
|
-
# needed chunks if the server recognises Range header
|
11
|
+
# It adds ability to fetch image meta from HTTP server while downloading only
|
12
|
+
# needed chunks if the server recognises Range header, otherwise fetches only
|
13
|
+
# required amount of data
|
13
14
|
class ImageSize
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def initialize(uri, redirects = 5)
|
18
|
-
if !@http || @http.address != uri.host || @http.port != uri.port
|
19
|
-
@http.finish if @http
|
20
|
-
@http = Net::HTTP.new(uri.host, uri.port)
|
21
|
-
@http.use_ssl = true if uri.scheme == 'https'
|
22
|
-
@http.start
|
23
|
-
end
|
15
|
+
module URIReader # :nodoc:
|
16
|
+
module HTTPChunkyReader # :nodoc:
|
17
|
+
include ChunkyReader
|
24
18
|
|
25
|
-
|
26
|
-
|
19
|
+
def chunk_range_header(i)
|
20
|
+
{ 'Range' => "bytes=#{chunk_size * i}-#{(chunk_size * (i + 1)) - 1}" }
|
21
|
+
end
|
22
|
+
end
|
27
23
|
|
28
|
-
|
29
|
-
|
30
|
-
raise "Too many redirects: #{response['location']}" unless redirects > 0
|
24
|
+
class BodyReader # :nodoc:
|
25
|
+
include ChunkyReader
|
31
26
|
|
32
|
-
|
33
|
-
|
34
|
-
@
|
35
|
-
when Net::HTTPPartialContent
|
36
|
-
@chunks = { 0 => response.body }
|
37
|
-
else
|
38
|
-
raise "Unexpected response: #{response}"
|
27
|
+
def initialize(response)
|
28
|
+
@body = String.new
|
29
|
+
@body_reader = response.to_enum(:read_body)
|
39
30
|
end
|
40
|
-
end
|
41
31
|
|
42
|
-
|
43
|
-
|
32
|
+
def [](offset, length)
|
33
|
+
if @body_reader
|
34
|
+
begin
|
35
|
+
@body << @body_reader.next while @body.length < offset + length
|
36
|
+
rescue StopIteration, IOError
|
37
|
+
@body_reader = nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
44
41
|
@body[offset, length]
|
45
|
-
else
|
46
|
-
super
|
47
42
|
end
|
48
43
|
end
|
49
44
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
raise "Unexpected response: #{response}"
|
58
|
-
end
|
45
|
+
class RangeReader # :nodoc:
|
46
|
+
include HTTPChunkyReader
|
47
|
+
|
48
|
+
def initialize(http, request_uri, chunk0)
|
49
|
+
@http = http
|
50
|
+
@request_uri = request_uri
|
51
|
+
@chunks = { 0 => chunk0 }
|
59
52
|
end
|
60
53
|
|
61
|
-
|
54
|
+
def chunk(i)
|
55
|
+
unless @chunks.key?(i)
|
56
|
+
response = @http.get(@request_uri, chunk_range_header(i))
|
57
|
+
case response
|
58
|
+
when Net::HTTPPartialContent
|
59
|
+
@chunks[i] = response.body
|
60
|
+
else
|
61
|
+
raise "Unexpected response: #{response}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
@chunks[i]
|
66
|
+
end
|
62
67
|
end
|
63
68
|
|
64
|
-
|
69
|
+
class << self
|
70
|
+
include HTTPChunkyReader
|
71
|
+
|
72
|
+
def open(uri, max_redirects = 5)
|
73
|
+
http = nil
|
74
|
+
(max_redirects + 1).times do
|
75
|
+
unless http && http.address == uri.host && http.port == uri.port
|
76
|
+
http.finish if http
|
77
|
+
|
78
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
79
|
+
http.use_ssl = true if uri.scheme == 'https'
|
80
|
+
http.start
|
81
|
+
end
|
65
82
|
|
66
|
-
|
67
|
-
|
83
|
+
response = http.request_get(uri.request_uri, chunk_range_header(0)) do |response_with_unread_body|
|
84
|
+
case response_with_unread_body
|
85
|
+
when Net::HTTPOK
|
86
|
+
return yield BodyReader.new(response_with_unread_body)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
case response
|
91
|
+
when Net::HTTPRedirection
|
92
|
+
uri += response['location']
|
93
|
+
when Net::HTTPPartialContent
|
94
|
+
return yield RangeReader.new(http, uri.request_uri, response.body)
|
95
|
+
when Net::HTTPRequestedRangeNotSatisfiable
|
96
|
+
return yield StringReader.new('')
|
97
|
+
else
|
98
|
+
raise "Unexpected response: #{response}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
raise "Too many redirects: #{uri}"
|
103
|
+
ensure
|
104
|
+
http.finish if http.started?
|
105
|
+
end
|
68
106
|
end
|
69
107
|
end
|
70
108
|
|
@@ -72,7 +110,7 @@ class ImageSize
|
|
72
110
|
class << self
|
73
111
|
def open_with_uri(input, &block)
|
74
112
|
if input.is_a?(URI)
|
75
|
-
|
113
|
+
URIReader.open(input, &block)
|
76
114
|
else
|
77
115
|
open_without_uri(input, &block)
|
78
116
|
end
|
data/lib/image_size.rb
CHANGED
@@ -76,6 +76,7 @@ private
|
|
76
76
|
def detect_format(ir)
|
77
77
|
head = ir[0, 1024]
|
78
78
|
case
|
79
|
+
when head.nil? || head.empty? then nil
|
79
80
|
when head[0, 6] =~ /GIF8[79]a/ then :gif
|
80
81
|
when head[0, 8] == "\211PNG\r\n\032\n" then detect_png_type(ir)
|
81
82
|
when head[0, 8] == "\212MNG\r\n\032\n" then :mng
|
@@ -56,9 +56,11 @@ describe ImageSize::ChunkyReader do
|
|
56
56
|
offsets.each do |offset_b|
|
57
57
|
length = offset_b - offset
|
58
58
|
expect(reader[offset, length]).to eq(data[offset, length]),
|
59
|
-
|
60
|
-
|
61
|
-
|
59
|
+
[
|
60
|
+
"for offset #{offset} and length #{length}",
|
61
|
+
"expected: #{data[offset, length].inspect}",
|
62
|
+
" got: #{reader[offset, length].inspect}",
|
63
|
+
].join("\n")
|
62
64
|
end
|
63
65
|
end
|
64
66
|
end
|
data/spec/image_size_spec.rb
CHANGED
@@ -7,31 +7,20 @@ require 'image_size/uri_reader'
|
|
7
7
|
|
8
8
|
require 'tempfile'
|
9
9
|
require 'shellwords'
|
10
|
-
|
10
|
+
|
11
|
+
require 'test_server'
|
11
12
|
|
12
13
|
describe ImageSize do
|
13
14
|
before :all do
|
14
|
-
@server =
|
15
|
-
:Logger => WEBrick::Log.new(StringIO.new),
|
16
|
-
:AccessLog => [],
|
17
|
-
:BindAddress => '127.0.0.1',
|
18
|
-
:Port => 0, # get the next available port
|
19
|
-
:DocumentRoot => '.',
|
20
|
-
})
|
21
|
-
@server_thread = Thread.new{ @server.start }
|
22
|
-
@server_base_url = URI("http://127.0.0.1:#{@server.config[:Port]}/")
|
15
|
+
@server = TestServer.new
|
23
16
|
end
|
24
17
|
|
25
18
|
after :all do
|
26
|
-
@server.
|
27
|
-
@server_thread.join
|
19
|
+
@server.finish
|
28
20
|
end
|
29
21
|
|
30
|
-
|
31
|
-
|
32
|
-
(Dir['spec/images/*/*.*'] + [__FILE__[%r{spec/.+?\z}]]).each do |path|
|
33
|
-
filesize = File.size(path)
|
34
|
-
warn "#{path} is too big #{filesize} (max #{max_filesize})" if filesize > max_filesize
|
22
|
+
Dir['spec/**/*'].each do |path|
|
23
|
+
next unless File.file?(path)
|
35
24
|
|
36
25
|
describe "for #{path}" do
|
37
26
|
let(:name){ File.basename(path) }
|
@@ -49,6 +38,15 @@ describe ImageSize do
|
|
49
38
|
}
|
50
39
|
end
|
51
40
|
let(:file_data){ File.open(path, 'rb', &:read) }
|
41
|
+
let(:file_size){ file_data.length }
|
42
|
+
|
43
|
+
before do
|
44
|
+
max_file_size = 16_384
|
45
|
+
|
46
|
+
if file_size > max_file_size
|
47
|
+
raise "reduce resulting gem size, #{path} is too big (#{file_size} > #{max_file_size})"
|
48
|
+
end
|
49
|
+
end
|
52
50
|
|
53
51
|
context 'given as data' do
|
54
52
|
it 'gets format and dimensions' do
|
@@ -65,7 +63,11 @@ describe ImageSize do
|
|
65
63
|
image_size = ImageSize.new(io)
|
66
64
|
expect(image_size).to have_attributes(attributes)
|
67
65
|
expect(io).not_to be_closed
|
68
|
-
|
66
|
+
if file_size.zero?
|
67
|
+
expect(io.pos).to be_zero
|
68
|
+
else
|
69
|
+
expect(io.pos).to_not be_zero
|
70
|
+
end
|
69
71
|
io.rewind
|
70
72
|
expect(io.read).to eq(file_data)
|
71
73
|
end
|
@@ -102,7 +104,11 @@ describe ImageSize do
|
|
102
104
|
image_size = ImageSize.new(io)
|
103
105
|
expect(image_size).to have_attributes(attributes)
|
104
106
|
expect(io).not_to be_closed
|
105
|
-
|
107
|
+
if file_size.zero?
|
108
|
+
expect(io.pos).to be_zero
|
109
|
+
else
|
110
|
+
expect(io.pos).to_not be_zero
|
111
|
+
end
|
106
112
|
io.rewind
|
107
113
|
expect(io.read).to eq(file_data)
|
108
114
|
end
|
@@ -117,9 +123,54 @@ describe ImageSize do
|
|
117
123
|
end
|
118
124
|
|
119
125
|
context 'fetching from webserver' do
|
120
|
-
|
121
|
-
|
122
|
-
|
126
|
+
let(:file_url){ @server.base_url + path }
|
127
|
+
|
128
|
+
context 'supporting range' do
|
129
|
+
context 'without redirects' do
|
130
|
+
it 'gets format and dimensions' do
|
131
|
+
image_size = ImageSize.url(file_url)
|
132
|
+
expect(image_size).to have_attributes(attributes)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'with redirects' do
|
137
|
+
it 'gets format and dimensions' do
|
138
|
+
image_size = ImageSize.url("#{file_url}?redirect=5")
|
139
|
+
expect(image_size).to have_attributes(attributes)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'with too many redirects' do
|
144
|
+
it 'gets format and dimensions' do
|
145
|
+
expect do
|
146
|
+
ImageSize.url("#{file_url}?redirect=6")
|
147
|
+
end.to raise_error(/Too many redirects/)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'not supporting range' do
|
153
|
+
context 'without redirects' do
|
154
|
+
it 'gets format and dimensions' do
|
155
|
+
image_size = ImageSize.url("#{file_url}?ignore_range")
|
156
|
+
expect(image_size).to have_attributes(attributes)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'with redirects' do
|
161
|
+
it 'gets format and dimensions' do
|
162
|
+
image_size = ImageSize.url("#{file_url}?ignore_range&redirect=5")
|
163
|
+
expect(image_size).to have_attributes(attributes)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'with too many redirects' do
|
168
|
+
it 'gets format and dimensions' do
|
169
|
+
expect do
|
170
|
+
ImageSize.url("#{file_url}?ignore_range&redirect=6")
|
171
|
+
end.to raise_error(/Too many redirects/)
|
172
|
+
end
|
173
|
+
end
|
123
174
|
end
|
124
175
|
end
|
125
176
|
end
|
data/spec/images/empty
ADDED
File without changes
|
data/spec/test_server.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'webrick'
|
4
|
+
|
5
|
+
class TestServer
|
6
|
+
attr_reader :base_url
|
7
|
+
|
8
|
+
def initialize(host = '127.0.0.1')
|
9
|
+
server_options = {
|
10
|
+
:Logger => WEBrick::Log.new(StringIO.new),
|
11
|
+
:AccessLog => [],
|
12
|
+
:BindAddress => host,
|
13
|
+
:Port => 0, # get the next available port
|
14
|
+
:DocumentRoot => '.',
|
15
|
+
:RequestCallback => proc do |req, res|
|
16
|
+
redirect = req.query['redirect'].to_i
|
17
|
+
if redirect > 0
|
18
|
+
res.set_redirect(
|
19
|
+
WEBrick::HTTPStatus::TemporaryRedirect,
|
20
|
+
[
|
21
|
+
req.request_uri.port == @base_url.port ? @second_url : @base_url,
|
22
|
+
req.request_uri.request_uri,
|
23
|
+
"?#{encode_www_form(req.query.merge('redirect' => redirect - 1))}",
|
24
|
+
].inject(:+)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
req.header.delete('range') if req.query['ignore_range']
|
29
|
+
end,
|
30
|
+
}
|
31
|
+
|
32
|
+
@server = WEBrick::HTTPServer.new(server_options)
|
33
|
+
@server.listen(host, 0) # listen on second port
|
34
|
+
|
35
|
+
@base_url = URI("http://#{host}:#{@server.listeners[0].addr[1]}/")
|
36
|
+
@second_url = URI("http://#{host}:#{@server.listeners[1].addr[1]}/")
|
37
|
+
|
38
|
+
@thread = Thread.new{ @server.start }
|
39
|
+
end
|
40
|
+
|
41
|
+
def finish
|
42
|
+
@server.shutdown
|
43
|
+
@thread.join
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
if URI.respond_to?(:encode_www_form)
|
49
|
+
def encode_www_form(h)
|
50
|
+
URI.encode_www_form(h)
|
51
|
+
end
|
52
|
+
else
|
53
|
+
require 'cgi'
|
54
|
+
|
55
|
+
def encode_www_form(h)
|
56
|
+
h.map do |k, v|
|
57
|
+
"#{CGI.escape(k)}=#{CGI.escape(v.to_s)}"
|
58
|
+
end.join('&')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_size
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keisuke Minami
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -31,14 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '1.
|
34
|
+
version: '1.22'
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '1.
|
41
|
+
version: '1.22'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: rubocop-rspec
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -61,6 +61,7 @@ extensions: []
|
|
61
61
|
extra_rdoc_files: []
|
62
62
|
files:
|
63
63
|
- ".github/workflows/check.yml"
|
64
|
+
- ".github/workflows/rubocop.yml"
|
64
65
|
- ".gitignore"
|
65
66
|
- ".rubocop.yml"
|
66
67
|
- ".rubocop_todo.yml"
|
@@ -85,6 +86,7 @@ files:
|
|
85
86
|
- spec/images/bmp/v3-bottom2top.42x50.bmp
|
86
87
|
- spec/images/bmp/v3-top2bottom.42x50.bmp
|
87
88
|
- spec/images/cur/32x256.cur
|
89
|
+
- spec/images/empty
|
88
90
|
- spec/images/gif/668x481.gif
|
89
91
|
- spec/images/ico/32x256.ico
|
90
92
|
- spec/images/jp2/163x402.jp2
|
@@ -118,13 +120,14 @@ files:
|
|
118
120
|
- spec/images/xbm/crlf.16x32.xbm
|
119
121
|
- spec/images/xpm/24x32.xpm
|
120
122
|
- spec/images/xpm/crlf.24x32.xpm
|
123
|
+
- spec/test_server.rb
|
121
124
|
homepage: https://github.com/toy/image_size
|
122
125
|
licenses:
|
123
126
|
- Ruby
|
124
127
|
metadata:
|
125
128
|
bug_tracker_uri: https://github.com/toy/image_size/issues
|
126
129
|
changelog_uri: https://github.com/toy/image_size/blob/master/CHANGELOG.markdown
|
127
|
-
documentation_uri: https://www.rubydoc.info/gems/image_size/3.0
|
130
|
+
documentation_uri: https://www.rubydoc.info/gems/image_size/3.1.0
|
128
131
|
source_code_uri: https://github.com/toy/image_size
|
129
132
|
post_install_message:
|
130
133
|
rdoc_options: []
|
@@ -141,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
144
|
- !ruby/object:Gem::Version
|
142
145
|
version: '0'
|
143
146
|
requirements: []
|
144
|
-
rubygems_version: 3.
|
147
|
+
rubygems_version: 3.3.11
|
145
148
|
signing_key:
|
146
149
|
specification_version: 4
|
147
150
|
summary: Measure image size using pure Ruby
|
@@ -154,6 +157,7 @@ test_files:
|
|
154
157
|
- spec/images/bmp/v3-bottom2top.42x50.bmp
|
155
158
|
- spec/images/bmp/v3-top2bottom.42x50.bmp
|
156
159
|
- spec/images/cur/32x256.cur
|
160
|
+
- spec/images/empty
|
157
161
|
- spec/images/gif/668x481.gif
|
158
162
|
- spec/images/ico/32x256.ico
|
159
163
|
- spec/images/jp2/163x402.jp2
|
@@ -187,3 +191,4 @@ test_files:
|
|
187
191
|
- spec/images/xbm/crlf.16x32.xbm
|
188
192
|
- spec/images/xpm/24x32.xpm
|
189
193
|
- spec/images/xpm/crlf.24x32.xpm
|
194
|
+
- spec/test_server.rb
|