format_parser 0.27.0 → 1.0.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 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