image_size 3.0.2 → 3.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +6 -0
- data/README.markdown +51 -1
- data/image_size.gemspec +1 -1
- data/lib/image_size/uri_reader.rb +83 -47
- data/spec/image_size/chunky_reader_spec.rb +5 -3
- data/spec/image_size_spec.rb +52 -15
- data/spec/test_server.rb +61 -0
- metadata +5 -3
    
        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/CHANGELOG.markdown
    CHANGED
    
    | @@ -2,6 +2,11 @@ | |
| 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 | 
            +
             | 
| 5 10 | 
             
            ## v3.0.2 (2022-05-19)
         | 
| 6 11 |  | 
| 7 12 | 
             
            * Fix handling empty files [#20](https://github.com/toy/image_size/issues/20) [@toy](https://github.com/toy)
         | 
| @@ -15,6 +20,7 @@ | |
| 15 20 | 
             
            * Read only required chunks of data for files and seekable IOs [@toy](https://github.com/toy)
         | 
| 16 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)
         | 
| 17 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)
         | 
| 18 24 |  | 
| 19 25 | 
             
            ## v2.1.2 (2021-08-21)
         | 
| 20 26 |  | 
    
        data/README.markdown
    CHANGED
    
    | @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            [](https://rubygems.org/gems/image_size)
         | 
| 2 2 | 
             
            [](https://github.com/toy/image_size/actions/workflows/check.yml)
         | 
| 3 | 
            +
            [](https://github.com/toy/image_size/actions/workflows/rubocop.yml)
         | 
| 3 4 |  | 
| 4 5 | 
             
            # image_size
         | 
| 5 6 |  | 
| @@ -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,6 +90,55 @@ 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).
         | 
    
        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}"
         | 
| @@ -6,67 +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 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
                  case response
         | 
| 29 | 
            -
                  when Net::HTTPRedirection
         | 
| 30 | 
            -
                    raise "Too many redirects: #{response['location']}" unless redirects > 0
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                    initialize(uri + response['location'], redirects - 1)
         | 
| 33 | 
            -
                  when Net::HTTPOK
         | 
| 34 | 
            -
                    @body = response.body
         | 
| 35 | 
            -
                  when Net::HTTPPartialContent
         | 
| 36 | 
            -
                    @chunks = { 0 => response.body }
         | 
| 37 | 
            -
                  when Net::HTTPRequestedRangeNotSatisfiable
         | 
| 38 | 
            -
                    @body = ''
         | 
| 39 | 
            -
                  else
         | 
| 40 | 
            -
                    raise "Unexpected response: #{response}"
         | 
| 19 | 
            +
                  def chunk_range_header(i)
         | 
| 20 | 
            +
                    { 'Range' => "bytes=#{chunk_size * i}-#{(chunk_size * (i + 1)) - 1}" }
         | 
| 41 21 | 
             
                  end
         | 
| 42 22 | 
             
                end
         | 
| 43 23 |  | 
| 44 | 
            -
                 | 
| 45 | 
            -
                   | 
| 24 | 
            +
                class BodyReader # :nodoc:
         | 
| 25 | 
            +
                  include ChunkyReader
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def initialize(response)
         | 
| 28 | 
            +
                    @body = String.new
         | 
| 29 | 
            +
                    @body_reader = response.to_enum(:read_body)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 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 | 
            +
             | 
| 46 41 | 
             
                    @body[offset, length]
         | 
| 47 | 
            -
                  else
         | 
| 48 | 
            -
                    super
         | 
| 49 42 | 
             
                  end
         | 
| 50 43 | 
             
                end
         | 
| 51 44 |  | 
| 52 | 
            -
                 | 
| 53 | 
            -
                   | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
                     | 
| 57 | 
            -
             | 
| 58 | 
            -
                     | 
| 59 | 
            -
                      raise "Unexpected response: #{response}"
         | 
| 60 | 
            -
                    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 }
         | 
| 61 52 | 
             
                  end
         | 
| 62 53 |  | 
| 63 | 
            -
                   | 
| 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
         | 
| 64 67 | 
             
                end
         | 
| 65 68 |  | 
| 66 | 
            -
             | 
| 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
         | 
| 67 82 |  | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 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
         | 
| 70 106 | 
             
                end
         | 
| 71 107 | 
             
              end
         | 
| 72 108 |  | 
| @@ -74,7 +110,7 @@ class ImageSize | |
| 74 110 | 
             
                class << self
         | 
| 75 111 | 
             
                  def open_with_uri(input, &block)
         | 
| 76 112 | 
             
                    if input.is_a?(URI)
         | 
| 77 | 
            -
                       | 
| 113 | 
            +
                      URIReader.open(input, &block)
         | 
| 78 114 | 
             
                    else
         | 
| 79 115 | 
             
                      open_without_uri(input, &block)
         | 
| 80 116 | 
             
                    end
         | 
| @@ -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,24 +7,16 @@ 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 22 | 
             
              Dir['spec/**/*'].each do |path|
         | 
| @@ -131,9 +123,54 @@ describe ImageSize do | |
| 131 123 | 
             
                  end
         | 
| 132 124 |  | 
| 133 125 | 
             
                  context 'fetching from webserver' do
         | 
| 134 | 
            -
                     | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 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
         | 
| 137 174 | 
             
                    end
         | 
| 138 175 | 
             
                  end
         | 
| 139 176 | 
             
                end
         | 
    
        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: 2022- | 
| 12 | 
            +
            date: 2022-09-16 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: rspec
         | 
| @@ -120,13 +120,14 @@ files: | |
| 120 120 | 
             
            - spec/images/xbm/crlf.16x32.xbm
         | 
| 121 121 | 
             
            - spec/images/xpm/24x32.xpm
         | 
| 122 122 | 
             
            - spec/images/xpm/crlf.24x32.xpm
         | 
| 123 | 
            +
            - spec/test_server.rb
         | 
| 123 124 | 
             
            homepage: https://github.com/toy/image_size
         | 
| 124 125 | 
             
            licenses:
         | 
| 125 126 | 
             
            - Ruby
         | 
| 126 127 | 
             
            metadata:
         | 
| 127 128 | 
             
              bug_tracker_uri: https://github.com/toy/image_size/issues
         | 
| 128 129 | 
             
              changelog_uri: https://github.com/toy/image_size/blob/master/CHANGELOG.markdown
         | 
| 129 | 
            -
              documentation_uri: https://www.rubydoc.info/gems/image_size/3.0 | 
| 130 | 
            +
              documentation_uri: https://www.rubydoc.info/gems/image_size/3.1.0
         | 
| 130 131 | 
             
              source_code_uri: https://github.com/toy/image_size
         | 
| 131 132 | 
             
            post_install_message:
         | 
| 132 133 | 
             
            rdoc_options: []
         | 
| @@ -190,3 +191,4 @@ test_files: | |
| 190 191 | 
             
            - spec/images/xbm/crlf.16x32.xbm
         | 
| 191 192 | 
             
            - spec/images/xpm/24x32.xpm
         | 
| 192 193 | 
             
            - spec/images/xpm/crlf.24x32.xpm
         | 
| 194 | 
            +
            - spec/test_server.rb
         |