mechanize 2.11.0 → 2.12.1

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: b4c0419c6395467b67e04d02f6fad693555635888226463874b23836dd481f74
4
- data.tar.gz: e9787a25ee371a1f9c5918c49cab30c89d6fb375ca1e6fffc7b444bc5dc5f7e1
3
+ metadata.gz: 7183879e98b1195380219464368f7761a6ee2b9adb3eb18f47b216e740d840d5
4
+ data.tar.gz: 9eaf999bb67a5f7f7625b1a77a4466b88a005d947003b67e155398f3af2b0bf5
5
5
  SHA512:
6
- metadata.gz: 23436f8664e13b44f71d5abb2b7b29a0a309e76880503c6ac68c19e1258d3e0dd73919f4b407f0dcfb3fe04dfeea0a350c0fcc967c2fee13085a69aa71992084
7
- data.tar.gz: 9869c25e459212cbff34f11e0cadcc985fff6e97bfad5012c091a9c594dd9a58ba2bc4afb7fed50c089cbe943a3adb9528968e80df01803869709508aaf9d218
6
+ metadata.gz: 3ba304c3a37d0eb98ccbbba83f425a68cb6ad2fb0da5d768a93cc8fd802f691da8fb86d7b6670888a597ca5f3f96ff755d6155197cbd1eef7c8db2442177bd72
7
+ data.tar.gz: db944be6db0079e9740c8e3aaade533baf990efbd87b6ebdbca034eb81a0adef82838fa50fd301f72d23c463109660a3256d0fae7f0154c8393a97b24ab214a1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Mechanize CHANGELOG
2
2
 
3
+ ## 2.12.1 / 2024-08-21
4
+
5
+ * Introduce experimental support for handling Zstd-compressed responses (CRuby only). (#652) @adrianodennanni
6
+
7
+
8
+ ## 2.12.0 / 2024-07-29
9
+
10
+ * Introduce experimental support for handling Brotli-compressed responses (CRuby only). (#650) @weshatheleopard
11
+
12
+
3
13
  ## 2.11.0 / 2024-07-18
4
14
 
5
15
  * The `accept-charset` header is no longer sent. In early versions of Mechanize, circa 2007, this was a common header but now no modern browser sends it, and servers are instructed to ignore it. See #646 for an example of a server that is confused by its presence. (#647) @flavorjones
data/Gemfile CHANGED
@@ -1,3 +1,12 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ gem "minitest", "~> 5.14"
6
+ gem "rake", "~> 13.0"
7
+ gem "rdoc", "~> 6.3"
8
+ gem "rubocop", "~> 1.12"
9
+ unless RUBY_PLATFORM == 'java'
10
+ gem 'brotli', '>= 0.5'
11
+ gem 'zstd-ruby', '~> 1.5'
12
+ end
@@ -495,6 +495,63 @@ class Mechanize::HTTP::Agent
495
495
  body_io.close
496
496
  end
497
497
 
498
+ ##
499
+ # Decodes a Brotli-encoded +body_io+
500
+ #
501
+ # (Experimental, CRuby only) Although Mechanize will never request a Brotli-encoded response via
502
+ # `accept-encoding`, buggy servers may return brotli-encoded responses anyway. Let's try to handle
503
+ # that case if the Brotli gem is loaded.
504
+ #
505
+ # If you need to handle Brotli-encoded responses, install the 'brotli' gem and require it in your
506
+ # application. If the `Brotli` constant is defined, Mechanize will attempt to use it to inflate
507
+ # the response.
508
+ #
509
+ def content_encoding_brotli(body_io)
510
+ log.debug('deflate brotli body') if log
511
+
512
+ unless defined?(::Brotli)
513
+ raise Mechanize::Error, "cannot deflate brotli-encoded response. Please install and require the 'brotli' gem."
514
+ end
515
+
516
+ begin
517
+ return StringIO.new(Brotli.inflate(body_io.read))
518
+ rescue Brotli::Error
519
+ log.error("unable to brotli-inflate response") if log
520
+ raise Mechanize::Error, "error inflating brotli-encoded response."
521
+ end
522
+ ensure
523
+ body_io.close
524
+ end
525
+
526
+ ##
527
+ # Decodes a Zstd-encoded +body_io+
528
+ #
529
+ # (Experimental, CRuby only) Although Mechanize will never request a zstd-encoded response via
530
+ # `accept-encoding`, buggy servers may return zstd-encoded responses, or you might need to
531
+ # inform the zstd keyword on your Accept-Encoding headers. Let's try to handle those cases if
532
+ # the Zstd gem is loaded.
533
+ #
534
+ # If you need to handle Zstd-encoded responses, install the 'zstd-ruby' gem and require it in your
535
+ # application. If the `Zstd` constant is defined, Mechanize will attempt to use it to inflate
536
+ # the response.
537
+ #
538
+ def content_encoding_zstd(body_io)
539
+ log.debug('deflate zstd body') if log
540
+
541
+ unless defined?(::Zstd)
542
+ raise Mechanize::Error, "cannot deflate zstd-encoded response. Please install and require the 'zstd-ruby' gem."
543
+ end
544
+
545
+ begin
546
+ return StringIO.new(Zstd.decompress(body_io.read))
547
+ rescue StandardError
548
+ log.error("unable to zstd#decompress response") if log
549
+ raise Mechanize::Error, "error decompressing zstd-encoded response."
550
+ end
551
+ ensure
552
+ body_io.close
553
+ end
554
+
498
555
  def disable_keep_alive request
499
556
  request['connection'] = 'close' unless @keep_alive
500
557
  end
@@ -831,6 +888,10 @@ class Mechanize::HTTP::Agent
831
888
  content_encoding_inflate body_io
832
889
  when 'gzip', 'x-gzip' then
833
890
  content_encoding_gunzip body_io
891
+ when 'br' then
892
+ content_encoding_brotli body_io
893
+ when 'zstd' then
894
+ content_encoding_zstd body_io
834
895
  else
835
896
  raise Mechanize::Error,
836
897
  "unsupported content-encoding: #{response['Content-Encoding']}"
@@ -15,11 +15,6 @@ end
15
15
 
16
16
  require 'minitest/autorun'
17
17
 
18
- begin
19
- require 'minitest/pride'
20
- rescue LoadError
21
- end
22
-
23
18
  ##
24
19
  # A generic test case for testing mechanize. Using a subclass of
25
20
  # Mechanize::TestCase for your tests will create an isolated mechanize
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  class Mechanize
3
- VERSION = "2.11.0"
3
+ VERSION = "2.12.1"
4
4
  end
data/mechanize.gemspec CHANGED
@@ -71,9 +71,4 @@ Gem::Specification.new do |spec|
71
71
  spec.add_runtime_dependency("rubyntlm", ">= 0.6.3", "~> 0.6")
72
72
  spec.add_runtime_dependency("base64") # removed from bundled gems in 3.4, and needed by rubyntlm (which doesn't declare this dependency)
73
73
  spec.add_runtime_dependency("nkf") # removed from bundled gems in 3.4
74
-
75
- spec.add_development_dependency("minitest", "~> 5.14")
76
- spec.add_development_dependency("rake", "~> 13.0")
77
- spec.add_development_dependency("rdoc", "~> 6.3")
78
- spec.add_development_dependency("rubocop", "~> 1.12")
79
74
  end
@@ -2,6 +2,10 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'mechanize/test_case'
5
+ unless RUBY_PLATFORM == 'java'
6
+ require 'brotli'
7
+ require 'zstd-ruby'
8
+ end
5
9
 
6
10
  class TestMechanizeHttpAgent < Mechanize::TestCase
7
11
 
@@ -924,6 +928,86 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
924
928
  assert_equal 'part', body.read
925
929
  end
926
930
 
931
+ def test_response_content_encoding_brotli_when_brotli_not_loaded
932
+ skip("only test this on jruby which doesn't have brotli support") unless RUBY_ENGINE == 'jruby'
933
+
934
+ @res.instance_variable_set :@header, 'content-encoding' => %w[br]
935
+ body_io = StringIO.new("content doesn't matter for this test")
936
+
937
+ e = assert_raises(Mechanize::Error) do
938
+ @agent.response_content_encoding(@res, body_io)
939
+ end
940
+ assert_includes(e.message, "cannot deflate brotli-encoded response")
941
+
942
+ assert(body_io.closed?)
943
+ end
944
+
945
+ def test_response_content_encoding_brotli
946
+ skip("jruby does not have brotli support") if RUBY_ENGINE == 'jruby'
947
+
948
+ @res.instance_variable_set :@header, 'content-encoding' => %w[br]
949
+ body_io = StringIO.new(Brotli.deflate("this is compressed by brotli"))
950
+
951
+ body = @agent.response_content_encoding(@res, body_io)
952
+
953
+ assert_equal("this is compressed by brotli", body.read)
954
+ assert(body_io.closed?)
955
+ end
956
+
957
+ def test_response_content_encoding_brotli_corrupt
958
+ skip("jruby does not have brotli support") if RUBY_ENGINE == 'jruby'
959
+
960
+ @res.instance_variable_set :@header, 'content-encoding' => %w[br]
961
+ body_io = StringIO.new("not a brotli payload")
962
+
963
+ e = assert_raises(Mechanize::Error) do
964
+ @agent.response_content_encoding(@res, body_io)
965
+ end
966
+ assert_includes(e.message, "error inflating brotli-encoded response")
967
+ assert_kind_of(Brotli::Error, e.cause)
968
+ assert(body_io.closed?)
969
+ end
970
+
971
+ def test_response_content_encoding_zstd_when_zstd_not_loaded
972
+ skip("only test this on jruby which doesn't have zstd support") unless RUBY_ENGINE == 'jruby'
973
+
974
+ @res.instance_variable_set :@header, 'content-encoding' => %w[zstd]
975
+ body_io = StringIO.new("content doesn't matter for this test")
976
+
977
+ e = assert_raises(Mechanize::Error) do
978
+ @agent.response_content_encoding(@res, body_io)
979
+ end
980
+ assert_includes(e.message, 'cannot deflate zstd-encoded response')
981
+
982
+ assert(body_io.closed?)
983
+ end
984
+
985
+ def test_response_content_encoding_zstd
986
+ skip('jruby does not have zstd support') if RUBY_ENGINE == 'jruby'
987
+
988
+ @res.instance_variable_set :@header, 'content-encoding' => %w[zstd]
989
+ body_io = StringIO.new(Zstd.compress('this is compressed by zstd'))
990
+
991
+ body = @agent.response_content_encoding(@res, body_io)
992
+
993
+ assert_equal('this is compressed by zstd', body.read)
994
+ assert(body_io.closed?)
995
+ end
996
+
997
+ def test_response_content_encoding_zstd_corrupt
998
+ skip('jruby does not have zstd support') if RUBY_ENGINE == 'jruby'
999
+
1000
+ @res.instance_variable_set :@header, 'content-encoding' => %w[zstd]
1001
+ body_io = StringIO.new('not a zstd payload')
1002
+
1003
+ e = assert_raises(Mechanize::Error) do
1004
+ @agent.response_content_encoding(@res, body_io)
1005
+ end
1006
+ assert_includes(e.message, 'error decompressing zstd-encoded response')
1007
+ assert_kind_of(RuntimeError, e.cause)
1008
+ assert(body_io.closed?)
1009
+ end
1010
+
927
1011
  def test_response_content_encoding_gzip_corrupt
928
1012
  log = StringIO.new
929
1013
  logger = Logger.new log
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mechanize
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.11.0
4
+ version: 2.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Hodel
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2024-07-18 00:00:00.000000000 Z
15
+ date: 2024-08-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: addressable
@@ -218,62 +218,6 @@ dependencies:
218
218
  - - ">="
219
219
  - !ruby/object:Gem::Version
220
220
  version: '0'
221
- - !ruby/object:Gem::Dependency
222
- name: minitest
223
- requirement: !ruby/object:Gem::Requirement
224
- requirements:
225
- - - "~>"
226
- - !ruby/object:Gem::Version
227
- version: '5.14'
228
- type: :development
229
- prerelease: false
230
- version_requirements: !ruby/object:Gem::Requirement
231
- requirements:
232
- - - "~>"
233
- - !ruby/object:Gem::Version
234
- version: '5.14'
235
- - !ruby/object:Gem::Dependency
236
- name: rake
237
- requirement: !ruby/object:Gem::Requirement
238
- requirements:
239
- - - "~>"
240
- - !ruby/object:Gem::Version
241
- version: '13.0'
242
- type: :development
243
- prerelease: false
244
- version_requirements: !ruby/object:Gem::Requirement
245
- requirements:
246
- - - "~>"
247
- - !ruby/object:Gem::Version
248
- version: '13.0'
249
- - !ruby/object:Gem::Dependency
250
- name: rdoc
251
- requirement: !ruby/object:Gem::Requirement
252
- requirements:
253
- - - "~>"
254
- - !ruby/object:Gem::Version
255
- version: '6.3'
256
- type: :development
257
- prerelease: false
258
- version_requirements: !ruby/object:Gem::Requirement
259
- requirements:
260
- - - "~>"
261
- - !ruby/object:Gem::Version
262
- version: '6.3'
263
- - !ruby/object:Gem::Dependency
264
- name: rubocop
265
- requirement: !ruby/object:Gem::Requirement
266
- requirements:
267
- - - "~>"
268
- - !ruby/object:Gem::Version
269
- version: '1.12'
270
- type: :development
271
- prerelease: false
272
- version_requirements: !ruby/object:Gem::Requirement
273
- requirements:
274
- - - "~>"
275
- - !ruby/object:Gem::Version
276
- version: '1.12'
277
221
  description: |-
278
222
  The Mechanize library is used for automating interaction with websites.
279
223
  Mechanize automatically stores and sends cookies, follows redirects,