format_parser 0.27.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a10ceeaca4d0d6d2336b94f9fc397781ae2ffabdb588cee7ebc59fdcb968082
4
- data.tar.gz: c28b8b7a0eb1d83e9f93406a4bbbad0699e50248d49d413393d6c3a6d82f7acf
3
+ metadata.gz: 04e71e127d550feb0a5aaa54a27cb68c1671e034a5d309c520e4b81ea385e865
4
+ data.tar.gz: 4617b5ea41651af01635d16dfba8de00f9765d1f3a092c7ec56170dd0d607495
5
5
  SHA512:
6
- metadata.gz: 6b3780e0f615f8a42aa097b652b675ceba5fb2325c3f2ad7472e178204cef3838967ea56c25e0daa1f5c666df42c5f5d4252a4dd42dae26389c41288d5b56d30
7
- data.tar.gz: f6f22e664f8603e691795b44902cc5d677f63a02b4950233ea09719b9b2e8ae7d9eea57e406bd4f5b9e252aff8e9c5a684cdb1155846f0eedeceeba7fe7131c0
6
+ metadata.gz: f6d059459bcc4813a657bbe6b4eebdbd667d7fb15497ea1cfad2e92e355a68388fd558cc28af4e383f8d909e4a4735d4a485e34d26f1bef7b02e2420650ee0a9
7
+ data.tar.gz: 990f6e2490a1c38b60e1ce0fcc8f9b3e0b5471ac429a04277171e59a61b0d60d2998834792a7ea124fe474f94446f411620539018ee15bfe176a4d767e1d5919
@@ -0,0 +1,100 @@
1
+ name: CI
2
+
3
+ on: [push,pull_request]
4
+
5
+ env:
6
+ BUNDLE_PATH: vendor/bundle
7
+
8
+ jobs:
9
+ lint:
10
+ name: Code Style
11
+ runs-on: ubuntu-18.04
12
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
13
+ strategy:
14
+ matrix:
15
+ ruby:
16
+ - 2.7
17
+ - 2.6
18
+ - 2.5
19
+ - jruby
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@v2
23
+ - name: Setup Ruby
24
+ uses: ruby/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby }}
27
+ - name: Gemfile Cache
28
+ uses: actions/cache@v2
29
+ with:
30
+ path: Gemfile.lock
31
+ key: ${{ runner.os }}-gemlock-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'format_parser.gemspec') }}
32
+ restore-keys: |
33
+ ${{ runner.os }}-gemlock-${{ matrix.ruby }}-
34
+ - name: Bundle Cache
35
+ id: cache-gems
36
+ uses: actions/cache@v2
37
+ with:
38
+ path: vendor/bundle
39
+ key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'Gemfile.lock', 'format_parser.gemspec') }}
40
+ restore-keys: |
41
+ ${{ runner.os }}-gems-${{ matrix.ruby }}-
42
+ ${{ runner.os }}-gems-
43
+ - name: Bundle Install
44
+ if: steps.cache-gems.outputs.cache-hit != 'true'
45
+ run: bundle install --jobs 4 --retry 3
46
+ - name: Rubocop Cache
47
+ uses: actions/cache@v2
48
+ with:
49
+ path: ~/.cache/rubocop_cache
50
+ key: ${{ runner.os }}-rubocop-${{ hashFiles('.rubocop.yml') }}
51
+ restore-keys: |
52
+ ${{ runner.os }}-rubocop-
53
+ - name: Rubocop
54
+ run: bundle exec rubocop
55
+ test:
56
+ name: Specs
57
+ runs-on: ubuntu-18.04
58
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
59
+ strategy:
60
+ matrix:
61
+ ruby:
62
+ - 2.7
63
+ - 2.6
64
+ - 2.5
65
+ - jruby
66
+ experimental: [false]
67
+ include:
68
+ - ruby: 3.1
69
+ experimental: true
70
+ - ruby: 3.0
71
+ experimental: true
72
+ steps:
73
+ - name: Checkout
74
+ uses: actions/checkout@v2
75
+ - name: Setup Ruby
76
+ uses: ruby/setup-ruby@v1
77
+ with:
78
+ ruby-version: ${{ matrix.ruby }}
79
+ - name: Gemfile Cache
80
+ uses: actions/cache@v2
81
+ with:
82
+ path: Gemfile.lock
83
+ key: ${{ runner.os }}-gemlock-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'format_parser.gemspec') }}
84
+ restore-keys: |
85
+ ${{ runner.os }}-gemlock-${{ matrix.ruby }}-
86
+ - name: Bundle Cache
87
+ id: cache-gems
88
+ uses: actions/cache@v2
89
+ with:
90
+ path: vendor/bundle
91
+ key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'Gemfile.lock', 'format_parser.gemspec') }}
92
+ restore-keys: |
93
+ ${{ runner.os }}-gems-${{ matrix.ruby }}-
94
+ ${{ runner.os }}-gems-
95
+ - name: Bundle Install
96
+ if: steps.cache-gems.outputs.cache-hit != 'true'
97
+ run: bundle install --jobs 4 --retry 3
98
+ - name: RSpec
99
+ continue-on-error: ${{ matrix.experimental }}
100
+ run: bundle exec rake parallel:spec
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 1.0.0
2
+ * Dropping support for Ruby 2.2.X, 2.3.X and 2.4.X
3
+ * MP3: Fix negative length reads in edge cases by bumping `id3tag` version to `v0.14.2`
4
+
5
+ ## 0.29.1
6
+ * Fix handling of 200 responses with `parse_http` as well as handling of very small responses which do not need range access
7
+
8
+ ## 0.29.0
9
+ * Add option `headers:` to `FormatParser.parse_http`
10
+
11
+ ## 0.28.0
12
+ * Change `FormatParser.parse_http` to follow HTTP redirects
13
+
1
14
  ## 0.27.0
2
15
  * Add `#content_type` on `Result` return values which makes sense for the detected filetype
3
16
 
@@ -32,8 +32,9 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_dependency 'ks', '~> 0.0'
34
34
  spec.add_dependency 'exifr', '~> 1', '>= 1.3.8'
35
- spec.add_dependency 'id3tag', '~> 0.14'
35
+ spec.add_dependency 'id3tag', '~> 0.14', '>= 0.14.2'
36
36
  spec.add_dependency 'faraday', '~> 0.13'
37
+ spec.add_dependency 'faraday_middleware', '~> 0.14'
37
38
  spec.add_dependency 'measurometer', '~> 1'
38
39
 
39
40
  spec.add_development_dependency 'rspec', '~> 3.0'
@@ -1,3 +1,3 @@
1
1
  module FormatParser
2
- VERSION = '0.27.0'
2
+ VERSION = '1.0.0'
3
3
  end
data/lib/format_parser.rb CHANGED
@@ -88,13 +88,14 @@ module FormatParser
88
88
  # given to `.parse`. The accepted keyword arguments are the same as the ones for `parse`.
89
89
  #
90
90
  # @param url[String, URI] the HTTP(S) URL to request the object from using Faraday and `Range:` requests
91
+ # @param headers[Hash] (optional) the HTTP headers to request the object from using Faraday
91
92
  # @param kwargs the keyword arguments to be delegated to `.parse`
92
93
  # @see {.parse}
93
- def self.parse_http(url, **kwargs)
94
+ def self.parse_http(url, headers: {}, **kwargs)
94
95
  # Do not extract the filename, since the URL
95
96
  # can really be "anything". But if the caller
96
97
  # provides filename_hint it will be carried over
97
- parse(RemoteIO.new(url), **kwargs)
98
+ parse(RemoteIO.new(url, headers: headers), **kwargs)
98
99
  end
99
100
 
100
101
  # Parses the file at the given `path` and returns the results as if it were any IO
data/lib/remote_io.rb CHANGED
@@ -24,8 +24,11 @@ class FormatParser::RemoteIO
24
24
  end
25
25
 
26
26
  # @param uri[URI, String] the remote URL to obtain
27
- def initialize(uri)
27
+ # @param headers[Hash] (optional) the HTTP headers to be used in the HTTP request
28
+ def initialize(uri, headers: {})
28
29
  require 'faraday'
30
+ require 'faraday_middleware/response/follow_redirects'
31
+ @headers = headers
29
32
  @uri = uri
30
33
  @pos = 0
31
34
  @remote_size = false
@@ -78,21 +81,40 @@ class FormatParser::RemoteIO
78
81
  # We use a GET and not a HEAD request followed by a GET because
79
82
  # S3 does not allow HEAD requests if you only presigned your URL for GETs, so we
80
83
  # combine the first GET of a segment and retrieving the size of the resource
81
- response = Faraday.get(@uri, nil, range: 'bytes=%d-%d' % [range.begin, range.end])
84
+ conn = Faraday.new(headers: @headers) do |faraday|
85
+ faraday.use FaradayMiddleware::FollowRedirects
86
+ # we still need the default adapter, more details: https://blog.thecodewhisperer.com/permalink/losing-time-to-faraday
87
+ faraday.adapter Faraday.default_adapter
88
+ end
89
+ response = conn.get(@uri, nil, range: 'bytes=%d-%d' % [range.begin, range.end])
82
90
 
83
91
  case response.status
84
- when 200, 206
92
+ when 200
93
+ # S3 returns 200 when you request a Range that is fully satisfied by the entire object,
94
+ # we take that into account here. Also, for very tiny responses (and also for empty responses)
95
+ # the responses are going to be 200 which does not mean we cannot proceed
96
+ # To have a good check for both of these conditions we need to know whether the ranges overlap fully
97
+ response_size = response.body.bytesize
98
+ requested_range_size = range.end - range.begin + 1
99
+ if response_size > requested_range_size
100
+ error_message = [
101
+ "We requested #{requested_range_size} bytes, but the server sent us more",
102
+ "(#{response_size} bytes) - it likely has no `Range:` support.",
103
+ "The error occurred when talking to #{@uri})"
104
+ ]
105
+ raise InvalidRequest.new(response.status, error_message.join("\n"))
106
+ end
107
+ [response_size, response.body]
108
+ when 206
85
109
  # Figure out of the server supports content ranges, if it doesn't we have no
86
110
  # business working with that server
87
111
  range_header = response.headers['Content-Range']
88
- raise InvalidRequest.new(response.status, "No range support at #{@uri}") unless range_header
112
+ raise InvalidRequest.new(response.status, "The server replied with 206 status but no Content-Range at #{@uri}") unless range_header
89
113
 
90
114
  # "Content-Range: bytes 0-0/307404381" is how the response header is structured
91
115
  size = range_header[/\/(\d+)$/, 1].to_i
92
116
 
93
- # S3 returns 200 when you request a Range that is fully satisfied by the entire object,
94
- # we take that into account here. For other servers, 206 is the expected response code.
95
- # Also, if we request a _larger_ range than what can be satisfied by the server,
117
+ # If we request a _larger_ range than what can be satisfied by the server,
96
118
  # the response is going to only contain what _can_ be sent and the status is also going
97
119
  # to be 206
98
120
  return [size, response.body]
@@ -53,19 +53,22 @@ end
53
53
  require 'minitest/autorun'
54
54
  require 'open-uri'
55
55
 
56
+ fixtures_dir = File.join(File.dirname(__FILE__), '../../fixtures')
57
+
56
58
  describe User do
57
59
  describe "profile_picture's metadatas" do
58
60
  it 'parse metadatas with format_parser' do
61
+ fixture_path = fixtures_dir + '/PNG/cat.png'
59
62
  user = User.create
60
63
  user.profile_picture.attach(
61
64
  filename: 'cat.png',
62
- io: URI.open('https://freesvg.org/img/1416155153.png')
65
+ io: File.open(fixture_path, 'rb')
63
66
  )
64
67
 
65
68
  user.profile_picture.analyze
66
69
 
67
- _(user.profile_picture.metadata[:width_px]).must_equal 500
68
- _(user.profile_picture.metadata[:height_px]).must_equal 296
70
+ _(user.profile_picture.metadata[:width_px]).must_equal 600
71
+ _(user.profile_picture.metadata[:height_px]).must_equal 600
69
72
  _(user.profile_picture.metadata[:color_mode]).must_equal 'rgba'
70
73
  end
71
74
  end
@@ -15,18 +15,31 @@ describe 'Fetching data from HTTP remotes' do
15
15
  }
16
16
  @server = WEBrick::HTTPServer.new(options)
17
17
  @server.mount '/', WEBrick::HTTPServlet::FileHandler, fixtures_dir
18
+ @server.mount_proc '/redirect' do |req, res|
19
+ res.status = 302
20
+ res.header['Location'] = req.path.sub('/redirect', '')
21
+ end
22
+ @server.mount_proc '/empty' do |_req, res|
23
+ res.status = 200
24
+ res.body = ''
25
+ end
26
+ @server.mount_proc '/tiny' do |_req, res|
27
+ res.status = 200
28
+ res.body = File.read(fixtures_dir + '/test.gif')
29
+ end
30
+
18
31
  trap('INT') { @server.stop }
19
32
  @server_thread = Thread.new { @server.start }
20
33
  end
21
34
 
22
- it '#parse_http is called without any option' do
35
+ it 'works with .parse_http called without any options' do
23
36
  result = FormatParser.parse_http('http://localhost:9399/PNG/anim.png')
24
37
 
25
38
  expect(result.format).to eq(:png)
26
39
  expect(result.height_px).to eq(180)
27
40
  end
28
41
 
29
- it '#parse_http is called with hash options' do
42
+ it 'works with .parse_http called with additional options' do
30
43
  fake_result = double(nature: :audio, format: :aiff)
31
44
  expect_any_instance_of(FormatParser::AIFFParser).to receive(:call).and_return(fake_result)
32
45
  results = FormatParser.parse_http('http://localhost:9399/PNG/anim.png', results: :all)
@@ -35,6 +48,18 @@ describe 'Fetching data from HTTP remotes' do
35
48
  expect(results).to include(fake_result)
36
49
  end
37
50
 
51
+ it 'is able to cope with a 0-size resource which does not provide Content-Range' do
52
+ file_information = FormatParser.parse_http('http://localhost:9399/empty')
53
+
54
+ expect(file_information).to be_nil
55
+ end
56
+
57
+ it 'is able to cope with a tiny resource which fits into the first requested range completely' do
58
+ file_information = FormatParser.parse_http('http://localhost:9399/tiny')
59
+ expect(file_information).not_to be_nil
60
+ expect(file_information.nature).to eq(:image)
61
+ end
62
+
38
63
  it 'parses the animated PNG over HTTP' do
39
64
  file_information = FormatParser.parse_http('http://localhost:9399/PNG/anim.png')
40
65
  expect(file_information).not_to be_nil
@@ -91,6 +116,32 @@ describe 'Fetching data from HTTP remotes' do
91
116
  end
92
117
  end
93
118
 
119
+ context 'when the server responds with a redirect' do
120
+ it 'follows the redirect' do
121
+ file_information = FormatParser.parse_http('http://localhost:9399/redirect/TIFF/test.tif')
122
+ expect(file_information.format).to eq(:tif)
123
+ end
124
+ end
125
+
126
+ it 'sends provided HTTP headers in the request' do
127
+ # Faraday is required only after calling .parse_http
128
+ # This line is just to trigger this require, then it's possible to
129
+ # add an expectation of how Faraday is initialized after.
130
+ FormatParser.parse_http('invalid_url') rescue nil
131
+
132
+ expect(Faraday)
133
+ .to receive(:new)
134
+ .with(headers: {'test-header' => 'test-value'})
135
+ .and_call_original
136
+
137
+ file_information = FormatParser.parse_http(
138
+ 'http://localhost:9399//TIFF/test.tif',
139
+ headers: {'test-header' => 'test-value'}
140
+ )
141
+
142
+ expect(file_information.format).to eq(:tif)
143
+ end
144
+
94
145
  after(:all) do
95
146
  @server.stop
96
147
  @server_thread.join(0.5)
@@ -7,7 +7,9 @@ describe FormatParser::RemoteIO do
7
7
  rio = described_class.new('https://images.invalid/img.jpg')
8
8
 
9
9
  fake_resp = double(headers: {'Content-Range' => '10-109/2577'}, status: 206, body: 'This is the response')
10
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=10-109').and_return(fake_resp)
10
+ faraday_conn = instance_double(Faraday::Connection, get: fake_resp)
11
+ allow(Faraday).to receive(:new).and_return(faraday_conn)
12
+ expect(faraday_conn).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=10-109')
11
13
 
12
14
  rio.seek(10)
13
15
  read_result = rio.read(100)
@@ -18,7 +20,9 @@ describe FormatParser::RemoteIO do
18
20
  rio = described_class.new('https://images.invalid/img.jpg')
19
21
 
20
22
  fake_resp = double(headers: {'Content-Range' => '10-109/2577'}, status: 200, body: 'This is the response')
21
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=10-109').and_return(fake_resp)
23
+ faraday_conn = instance_double(Faraday::Connection, get: fake_resp)
24
+ allow(Faraday).to receive(:new).and_return(faraday_conn)
25
+ expect(faraday_conn).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=10-109')
22
26
 
23
27
  rio.seek(10)
24
28
  read_result = rio.read(100)
@@ -29,7 +33,9 @@ describe FormatParser::RemoteIO do
29
33
  rio = described_class.new('https://images.invalid/img.jpg')
30
34
 
31
35
  fake_resp = double(headers: {}, status: 403, body: 'Please log in')
32
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
36
+ faraday_conn = instance_double(Faraday::Connection, get: fake_resp)
37
+ allow(Faraday).to receive(:new).and_return(faraday_conn)
38
+ expect(faraday_conn).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199')
33
39
 
34
40
  rio.seek(100)
35
41
  expect { rio.read(100) }.to raise_error(/replied with a 403 and refused/)
@@ -39,7 +45,9 @@ describe FormatParser::RemoteIO do
39
45
  rio = described_class.new('https://images.invalid/img.jpg')
40
46
 
41
47
  fake_resp = double(headers: {}, status: 416, body: 'You stepped off the ledge of the range')
42
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
48
+ faraday_conn = instance_double(Faraday::Connection, get: fake_resp)
49
+ allow(Faraday).to receive(:new).and_return(faraday_conn)
50
+ expect(faraday_conn).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199')
43
51
 
44
52
  rio.seek(100)
45
53
  expect(rio.read(100)).to be_nil
@@ -49,7 +57,9 @@ describe FormatParser::RemoteIO do
49
57
  rio = described_class.new('https://images.invalid/img.jpg')
50
58
 
51
59
  fake_resp = double(headers: {}, status: 403, body: 'Please log in')
52
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
60
+ faraday_conn = instance_double(Faraday::Connection, get: fake_resp)
61
+ allow(Faraday).to receive(:new).and_return(faraday_conn)
62
+ expect(faraday_conn).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199')
53
63
 
54
64
  rio.seek(100)
55
65
  # rubocop: disable Lint/AmbiguousBlockAssociation
@@ -60,7 +70,9 @@ describe FormatParser::RemoteIO do
60
70
  rio = described_class.new('https://images.invalid/img.jpg')
61
71
 
62
72
  fake_resp = double(headers: {}, status: 416, body: 'You jumped off the end of the file maam')
63
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
73
+ faraday_conn = instance_double(Faraday::Connection, get: fake_resp)
74
+ allow(Faraday).to receive(:new).and_return(faraday_conn)
75
+ expect(faraday_conn).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199')
64
76
 
65
77
  rio.seek(100)
66
78
  expect(rio.read(100)).to be_nil
@@ -69,15 +81,24 @@ describe FormatParser::RemoteIO do
69
81
  it 'does not overwrite size when the range cannot be satisfied and the response is 416' do
70
82
  rio = described_class.new('https://images.invalid/img.jpg')
71
83
 
72
- fake_resp = double(headers: {'Content-Range' => 'bytes 0-0/13'}, status: 206, body: 'a')
73
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=0-0').and_return(fake_resp)
84
+ fake_resp1 = double(headers: {'Content-Range' => 'bytes 0-0/13'}, status: 206, body: 'a')
85
+ fake_resp2 = double(headers: {}, status: 416, body: 'You jumped off the end of the file maam')
86
+
87
+ faraday_conn = instance_double(Faraday::Connection)
88
+ allow(Faraday).to receive(:new).and_return(faraday_conn)
89
+ expect(faraday_conn).to receive(:get)
90
+ .with('https://images.invalid/img.jpg', nil, range: 'bytes=0-0')
91
+ .ordered
92
+ .and_return(fake_resp1)
93
+ expect(faraday_conn).to receive(:get)
94
+ .with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199')
95
+ .ordered
96
+ .and_return(fake_resp2)
97
+
74
98
  rio.read(1)
75
99
 
76
100
  expect(rio.size).to eq(13)
77
101
 
78
- fake_resp = double(headers: {}, status: 416, body: 'You jumped off the end of the file maam')
79
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
80
-
81
102
  rio.seek(100)
82
103
  expect(rio.read(100)).to be_nil
83
104
 
@@ -88,7 +109,9 @@ describe FormatParser::RemoteIO do
88
109
  rio = described_class.new('https://images.invalid/img.jpg')
89
110
 
90
111
  fake_resp = double(headers: {}, status: 502, body: 'Guru meditation')
91
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
112
+ faraday_conn = instance_double(Faraday::Connection, get: fake_resp)
113
+ allow(Faraday).to receive(:new).and_return(faraday_conn)
114
+ expect(faraday_conn).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199')
92
115
 
93
116
  rio.seek(100)
94
117
  expect { rio.read(100) }.to raise_error(/replied with a 502 and we might want to retry/)
@@ -100,7 +123,9 @@ describe FormatParser::RemoteIO do
100
123
  expect(rio.pos).to eq(0)
101
124
 
102
125
  fake_resp = double(headers: {'Content-Range' => 'bytes 0-0/13'}, status: 206, body: 'a')
103
- expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=0-0').and_return(fake_resp)
126
+ faraday_conn = instance_double(Faraday::Connection, get: fake_resp)
127
+ allow(Faraday).to receive(:new).and_return(faraday_conn)
128
+ expect(faraday_conn).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=0-0')
104
129
  rio.read(1)
105
130
 
106
131
  expect(rio.pos).to eq(1)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: format_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noah Berman
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-01-26 00:00:00.000000000 Z
12
+ date: 2022-01-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ks
@@ -52,6 +52,9 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.14'
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 0.14.2
55
58
  type: :runtime
56
59
  prerelease: false
57
60
  version_requirements: !ruby/object:Gem::Requirement
@@ -59,6 +62,9 @@ dependencies:
59
62
  - - "~>"
60
63
  - !ruby/object:Gem::Version
61
64
  version: '0.14'
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 0.14.2
62
68
  - !ruby/object:Gem::Dependency
63
69
  name: faraday
64
70
  requirement: !ruby/object:Gem::Requirement
@@ -73,6 +79,20 @@ dependencies:
73
79
  - - "~>"
74
80
  - !ruby/object:Gem::Version
75
81
  version: '0.13'
82
+ - !ruby/object:Gem::Dependency
83
+ name: faraday_middleware
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.14'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.14'
76
96
  - !ruby/object:Gem::Dependency
77
97
  name: measurometer
78
98
  requirement: !ruby/object:Gem::Requirement
@@ -183,10 +203,10 @@ executables:
183
203
  extensions: []
184
204
  extra_rdoc_files: []
185
205
  files:
206
+ - ".github/workflows/main.yml"
186
207
  - ".gitignore"
187
208
  - ".rspec"
188
209
  - ".rubocop.yml"
189
- - ".travis.yml"
190
210
  - CHANGELOG.md
191
211
  - CODE_OF_CONDUCT.md
192
212
  - CONTRIBUTING.md
@@ -295,7 +315,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
295
315
  - !ruby/object:Gem::Version
296
316
  version: '0'
297
317
  requirements: []
298
- rubygems_version: 3.0.3
318
+ rubygems_version: 3.1.6
299
319
  signing_key:
300
320
  specification_version: 4
301
321
  summary: A library for efficient parsing of file metadata
data/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- rvm:
2
- - 2.2.10
3
- - 2.3.8
4
- - 2.4.9
5
- - 2.5.8
6
- - 2.6.6
7
- - 2.7.2
8
- - jruby
9
- sudo: false
10
- cache: bundler
11
- script:
12
- - bundle exec rake