mechanize 2.2.1 → 2.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mechanize might be problematic. Click here for more details.

data.tar.gz.sig CHANGED
Binary file
@@ -1,5 +1,25 @@
1
1
  = Mechanize CHANGELOG
2
2
 
3
+ === 2.3 / 2012-02-20
4
+
5
+ * Minor enhancement
6
+ * Add support for the Max-Age attribute in the Set-Cookie header.
7
+ * Added Mechanize::Download#body for compatibility with Mechanize::File when
8
+ using Mechanize#get_file with Mechanize::Image or other Download-based
9
+ pluggable parser. Issue #202 by angas
10
+ * Mechanize#max_file_buffer may be set to nil to disable creation of
11
+ Tempfiles.
12
+
13
+ * Bug fixes
14
+ * Applied Mechanize#max_file_buffer to the Content-Encoding handlers as well
15
+ to prevent extra Tempfiles for small gzip or deflate response
16
+ * Increased the default Mechanize#max_file_buffer to 100,000 bytes. This
17
+ gives ~5MB of response bodies in memory with the default history setting
18
+ of 50 pages (depending on GC behavior).
19
+ * Ignore empty path/domain attributes.
20
+ * Cookies with an empty Expires attribute value were stored as session
21
+ cookies but cookies without the Expires attribute were not. Issue #78
22
+
3
23
  === 2.2.1 / 2012-02-13
4
24
 
5
25
  * Bug fixes
@@ -1,7 +1,7 @@
1
1
  = Mechanize
2
2
 
3
3
  * http://mechanize.rubyforge.org
4
- * http://github.com/tenderlove/mechanize/tree/master
4
+ * https://github.com/tenderlove/mechanize
5
5
 
6
6
  == DESCRIPTION
7
7
 
@@ -24,7 +24,7 @@ The mechanize mailing list is available here:
24
24
 
25
25
  The bug tracker is available here:
26
26
 
27
- * http://github.com/tenderlove/mechanize/issues
27
+ * https://github.com/tenderlove/mechanize/issues
28
28
 
29
29
  == Examples
30
30
 
@@ -40,7 +40,7 @@ Copyright (c) 2006-2011:
40
40
  * {Aaron Patterson}[http://tenderlovemaking.com] (aaronp@rubyforge.org)
41
41
  * {Mike Dalessio}[http://mike.daless.io] (mike@csa.net)
42
42
 
43
- Copyright (c) 2011:
43
+ Copyright (c) 2011-2012:
44
44
 
45
45
  * {Eric Hodel}[http://blog.segment7.net] (drbrain@segment7.net)
46
46
  * {Akinori MUSHA}[http://blog.akinori.org] (knu@idaemons.org)
@@ -73,7 +73,7 @@ class Mechanize
73
73
  ##
74
74
  # The version of Mechanize you are using.
75
75
 
76
- VERSION = '2.2.1'
76
+ VERSION = '2.3'
77
77
 
78
78
  ##
79
79
  # Base mechanize error class
@@ -207,7 +207,9 @@ class Mechanize
207
207
  end
208
208
 
209
209
  ##
210
- # Maximum number of items allowed in the history.
210
+ # Maximum number of items allowed in the history. The default setting is 50
211
+ # pages. Note that the size of the history multiplied by the maximum
212
+ # response body size
211
213
 
212
214
  def max_history
213
215
  @agent.history.max_size
@@ -217,9 +219,11 @@ class Mechanize
217
219
  # Sets the maximum number of items allowed in the history to +length+.
218
220
  #
219
221
  # Setting the maximum history length to nil will make the history size
220
- # unlimited. Take care when doing this, mechanize stores page bodies in the
221
- # temporary files directory for pages in the history. For a long-running
222
- # mechanize program this can be quite large.
222
+ # unlimited. Take care when doing this, mechanize stores response bodies in
223
+ # memory for pages and in the temporary files directory for other responses.
224
+ # For a long-running mechanize program this can be quite large.
225
+ #
226
+ # See also the discussion under #max_file_buffer=
223
227
 
224
228
  def max_history= length
225
229
  @agent.history.max_size = length
@@ -295,7 +299,7 @@ class Mechanize
295
299
  end
296
300
  if link.noreferrer?
297
301
  href = @agent.resolve(link.href, link.page || current_page)
298
- referer = Page.new(nil, {'content-type'=>'text/html'})
302
+ referer = Page.new
299
303
  else
300
304
  href = link.href
301
305
  end
@@ -382,9 +386,9 @@ class Mechanize
382
386
 
383
387
  referer ||=
384
388
  if uri.to_s =~ %r{\Ahttps?://}
385
- Page.new(nil, 'content-type' => 'text/html')
389
+ Page.new
386
390
  else
387
- current_page || Page.new(nil, 'content-type' => 'text/html')
391
+ current_page || Page.new
388
392
  end
389
393
 
390
394
  # FIXME: Huge hack so that using a URI as a referer works. I need to
@@ -392,9 +396,9 @@ class Mechanize
392
396
  # Mechanize::Page#base
393
397
  unless Mechanize::Parser === referer then
394
398
  referer = if referer.is_a?(String) then
395
- Page.new URI(referer), 'content-type' => 'text/html'
399
+ Page.new URI(referer)
396
400
  else
397
- Page.new referer, 'content-type' => 'text/html'
401
+ Page.new referer
398
402
  end
399
403
  end
400
404
 
@@ -479,7 +483,7 @@ class Mechanize
479
483
  # as the request body, if allowed.
480
484
 
481
485
  def request_with_entity(verb, uri, entity, headers = {})
482
- cur_page = current_page || Page.new(nil, {'content-type'=>'text/html'})
486
+ cur_page = current_page || Page.new
483
487
 
484
488
  headers = {
485
489
  'Content-Type' => 'application/octet-stream',
@@ -757,7 +761,9 @@ class Mechanize
757
761
 
758
762
  ##
759
763
  # Responses larger than this will be written to a Tempfile instead of stored
760
- # in memory. The default is 10240 bytes
764
+ # in memory. The default is 100,000 bytes.
765
+ #
766
+ # A value of nil disables creation of Tempfiles.
761
767
 
762
768
  def max_file_buffer
763
769
  @agent.max_file_buffer
@@ -765,7 +771,16 @@ class Mechanize
765
771
 
766
772
  ##
767
773
  # Sets the maximum size of a response body that will be stored in memory to
768
- # +bytes+
774
+ # +bytes+. A value of nil causes all response bodies to be stored in
775
+ # memory.
776
+ #
777
+ # Note that for Mechanize::Download subclasses, the maximum buffer size
778
+ # multiplied by the number of pages stored in history (controlled by
779
+ # #max_history) is an approximate upper limit on the amount of memory
780
+ # Mechanize will use. By default, Mechanize can use up to ~5MB to store
781
+ # response bodies for non-File and non-Page (HTML) responses.
782
+ #
783
+ # See also the discussion under #max_history=
769
784
 
770
785
  def max_file_buffer= bytes
771
786
  @agent.max_file_buffer = bytes
@@ -1152,7 +1167,7 @@ class Mechanize
1152
1167
 
1153
1168
  def post_form(uri, form, headers = {})
1154
1169
  cur_page = form.page || current_page ||
1155
- Page.new(nil, {'content-type'=>'text/html'})
1170
+ Page.new
1156
1171
 
1157
1172
  request_data = form.request_data
1158
1173
 
@@ -1,5 +1,5 @@
1
1
  require 'time'
2
- require 'webrick/cookie'
2
+ require 'webrick/httputils'
3
3
  require 'domain_name'
4
4
 
5
5
  # This class is used to represent an HTTP Cookie.
@@ -93,12 +93,13 @@ class Mechanize::Cookie
93
93
 
94
94
  cookie_elem.each do |pair|
95
95
  pair.strip!
96
- key, value = pair.split(/\=/, 2)
96
+ key, value = pair.split(/=/, 2)
97
97
  next unless key
98
98
  value = WEBrick::HTTPUtils.dequote(value.strip) if value
99
99
 
100
100
  case key.downcase
101
101
  when 'domain'
102
+ next unless value && !value.empty?
102
103
  begin
103
104
  cookie.domain = value
104
105
  cookie.for_domain = true
@@ -106,27 +107,27 @@ class Mechanize::Cookie
106
107
  log.warn("Couldn't parse domain: #{value}") if log
107
108
  end
108
109
  when 'path'
110
+ next unless value && !value.empty?
109
111
  cookie.path = value
110
112
  when 'expires'
111
- if value.empty?
112
- cookie.session = true
113
- next
114
- end
115
-
113
+ next unless value && !value.empty?
116
114
  begin
117
115
  cookie.expires = Time::parse(value)
118
116
  rescue
119
117
  log.warn("Couldn't parse expires: #{value}") if log
120
118
  end
121
119
  when 'max-age'
120
+ next unless value && !value.empty?
122
121
  begin
123
122
  cookie.max_age = Integer(value)
124
123
  rescue
125
124
  log.warn("Couldn't parse max age '#{value}'") if log
126
125
  end
127
126
  when 'comment'
127
+ next unless value
128
128
  cookie.comment = value
129
129
  when 'version'
130
+ next unless value
130
131
  begin
131
132
  cookie.version = Integer(value)
132
133
  rescue
@@ -141,6 +142,11 @@ class Mechanize::Cookie
141
142
  cookie.path ||= (uri + './').path
142
143
  cookie.secure ||= false
143
144
  cookie.domain ||= uri.host
145
+
146
+ # RFC 6265 4.1.2.2
147
+ cookie.expires = Time.now + cookie.max_age if cookie.max_age
148
+ cookie.session = !cookie.expires
149
+
144
150
  # Move this in to the cookie jar
145
151
  yield cookie if block_given?
146
152
 
@@ -40,6 +40,15 @@ class Mechanize::Download
40
40
  yield self if block_given?
41
41
  end
42
42
 
43
+ ##
44
+ # The body of this response as a String.
45
+ #
46
+ # Take care, this may use lots of memory if the response body is large.
47
+
48
+ def body
49
+ @body_io.read.tap { @body_io.rewind }
50
+ end
51
+
43
52
  ##
44
53
  # Saves a copy of the body_io to +filename+
45
54
 
@@ -98,7 +98,7 @@ class Mechanize::HTTP::Agent
98
98
  attr_accessor :cookie_jar
99
99
 
100
100
  # Responses larger than this will be written to a Tempfile instead of stored
101
- # in memory.
101
+ # in memory. Setting this to nil disables creation of Tempfiles.
102
102
  attr_accessor :max_file_buffer
103
103
 
104
104
  # :section: Utility
@@ -126,7 +126,7 @@ class Mechanize::HTTP::Agent
126
126
  @gzip_enabled = true
127
127
  @history = Mechanize::History.new
128
128
  @keep_alive = true
129
- @max_file_buffer = 10240
129
+ @max_file_buffer = 100_000 # 5MB for response bodies
130
130
  @open_timeout = nil
131
131
  @post_connect_hooks = []
132
132
  @pre_connect_hooks = []
@@ -375,14 +375,7 @@ class Mechanize::HTTP::Agent
375
375
  log.debug('gzip response') if log
376
376
 
377
377
  zio = Zlib::GzipReader.new body_io
378
- out_io = Tempfile.new 'mechanize-decode'
379
- out_io.unlink
380
- out_io.binmode
381
-
382
- until zio.eof? do
383
- out_io.write zio.read 16384
384
- end
385
-
378
+ out_io = auto_io 'mechanize-gunzip', 16384, zio
386
379
  zio.finish
387
380
 
388
381
  return out_io
@@ -400,6 +393,7 @@ class Mechanize::HTTP::Agent
400
393
  end
401
394
  ensure
402
395
  zio.close if zio and not zio.closed?
396
+ body_io.close unless body_io.closed?
403
397
  end
404
398
 
405
399
  ##
@@ -421,6 +415,8 @@ class Mechanize::HTTP::Agent
421
415
  log.error("unable to inflate response: #{e}") if log
422
416
  raise
423
417
  end
418
+ ensure
419
+ body_io.close
424
420
  end
425
421
 
426
422
  def disable_keep_alive request
@@ -739,7 +735,10 @@ class Mechanize::HTTP::Agent
739
735
  raise Mechanize::Error, message
740
736
  ensure
741
737
  begin
742
- body_io.close! if Tempfile === body_io and out_io.path != body_io.path
738
+ if Tempfile === body_io and
739
+ (StringIO === out_io or out_io.path != body_io.path) then
740
+ body_io.close!
741
+ end
743
742
  rescue IOError
744
743
  # HACK ruby 1.8 raises IOError when closing the stream
745
744
  end
@@ -783,7 +782,7 @@ class Mechanize::HTTP::Agent
783
782
  sleep delay
784
783
  @history.push(page, page.uri)
785
784
  fetch new_url, :get, {}, [],
786
- Mechanize::Page.new(nil, {'content-type'=>'text/html'}), redirects
785
+ Mechanize::Page.new, redirects
787
786
  end
788
787
 
789
788
  def response_log response
@@ -804,7 +803,7 @@ class Mechanize::HTTP::Agent
804
803
  def response_read response, request, uri
805
804
  content_length = response.content_length
806
805
 
807
- if content_length and content_length > @max_file_buffer then
806
+ if use_tempfile? content_length then
808
807
  body_io = Tempfile.new 'mechanize-raw'
809
808
  body_io.unlink
810
809
  body_io.binmode if defined? body_io.binmode
@@ -819,7 +818,7 @@ class Mechanize::HTTP::Agent
819
818
  response.read_body { |part|
820
819
  total += part.length
821
820
 
822
- if StringIO === body_io and total > @max_file_buffer then
821
+ if StringIO === body_io and use_tempfile? total then
823
822
  new_io = Tempfile.new 'mechanize-raw'
824
823
  new_io.unlink
825
824
  new_io.binmode
@@ -1034,17 +1033,52 @@ class Mechanize::HTTP::Agent
1034
1033
 
1035
1034
  # :section: Utility
1036
1035
 
1036
+ ##
1037
+ # Creates a new output IO by reading +input_io+ in +read_size+ chunks. If
1038
+ # the output is over the max_file_buffer size a Tempfile with +name+ is
1039
+ # created.
1040
+ #
1041
+ # If a block is provided, each chunk of +input_io+ is yielded for further
1042
+ # processing.
1043
+
1044
+ def auto_io name, read_size, input_io
1045
+ out_io = StringIO.new
1046
+
1047
+ out_io.set_encoding Encoding::BINARY if out_io.respond_to? :set_encoding
1048
+
1049
+ until input_io.eof? do
1050
+ if StringIO === out_io and use_tempfile? out_io.size then
1051
+ new_io = Tempfile.new name
1052
+ new_io.unlink
1053
+ new_io.binmode
1054
+
1055
+ new_io.write out_io.string
1056
+ out_io = new_io
1057
+ end
1058
+
1059
+ chunk = input_io.read read_size
1060
+ chunk = yield chunk if block_given?
1061
+
1062
+ out_io.write chunk
1063
+ end
1064
+
1065
+ out_io.rewind
1066
+
1067
+ out_io
1068
+ end
1069
+
1037
1070
  def inflate compressed, window_bits = nil
1038
1071
  inflate = Zlib::Inflate.new window_bits
1039
- out_io = Tempfile.new 'mechanize-decode'
1040
1072
 
1041
- until compressed.eof? do
1042
- out_io.write inflate.inflate compressed.read 1024
1073
+ out_io = auto_io 'mechanize-inflate', 1024, compressed do |chunk|
1074
+ inflate.inflate chunk
1043
1075
  end
1044
1076
 
1045
1077
  out_io.write inflate.finish
1046
1078
 
1047
1079
  out_io
1080
+ ensure
1081
+ inflate.close
1048
1082
  end
1049
1083
 
1050
1084
  def log
@@ -1083,5 +1117,12 @@ class Mechanize::HTTP::Agent
1083
1117
  @http.proxy = proxy_uri
1084
1118
  end
1085
1119
 
1120
+ def use_tempfile? size
1121
+ return false unless @max_file_buffer
1122
+ return false unless size
1123
+
1124
+ size >= @max_file_buffer
1125
+ end
1126
+
1086
1127
  end
1087
1128
 
@@ -13,6 +13,10 @@ class Mechanize::Page < Mechanize::File
13
13
  extend Forwardable
14
14
  extend Mechanize::ElementMatcher
15
15
 
16
+ DEFAULT_RESPONSE = {
17
+ 'content-type' => 'text/html',
18
+ }.freeze
19
+
16
20
  attr_accessor :mech
17
21
 
18
22
  ##
@@ -21,8 +25,9 @@ class Mechanize::Page < Mechanize::File
21
25
  attr_reader :encodings
22
26
 
23
27
  def initialize(uri=nil, response=nil, body=nil, code=nil, mech=nil)
28
+ response ||= DEFAULT_RESPONSE
24
29
  raise Mechanize::ContentTypeError, response['content-type'] unless
25
- response['content-type'] =~ /^(text\/html)|(application\/xhtml\+xml)/i
30
+ response['content-type'] =~ %r{\A(?:text/html|application/xhtml\+xml)(?:$|\s*[\s;,])}i
26
31
 
27
32
  @meta_content_type = nil
28
33
  @encoding = nil
@@ -16,6 +16,10 @@ require 'mechanize/page'
16
16
  # Mechanize::File. For large files you should subclass Mechanize::Download as
17
17
  # the content is only loaded into memory in small chunks.
18
18
  #
19
+ # When writing your own pluggable parser, be sure to provide a method #body
20
+ # that returns a String containing the response body for compatibility with
21
+ # Mechanize#get_file.
22
+ #
19
23
  # == Example
20
24
  #
21
25
  # To create your own parser, just create a class that takes four parameters in
@@ -38,9 +38,7 @@ class Mechanize::TestCase < MiniTest::Unit::TestCase
38
38
  </html>
39
39
  END
40
40
 
41
- response = { 'content-type' => 'text/html' }
42
-
43
- Mechanize::Page.new uri, response, html, 200, agent
41
+ Mechanize::Page.new uri, nil, html, 200, agent
44
42
  end
45
43
 
46
44
  def have_encoding?
@@ -49,7 +47,7 @@ class Mechanize::TestCase < MiniTest::Unit::TestCase
49
47
 
50
48
  def html_page body
51
49
  uri = URI 'http://example/'
52
- Mechanize::Page.new uri, { 'content-type' => 'text/html' }, body, 200, @mech
50
+ Mechanize::Page.new uri, nil, body, 200, @mech
53
51
  end
54
52
 
55
53
  def in_tmpdir
@@ -388,13 +388,6 @@ but not <a href="/" rel="me nofollow">this</a>!
388
388
  assert block_called
389
389
  end
390
390
 
391
- def test_get_file
392
- page = @mech.get("http://localhost/frame_test.html")
393
- content_length = page.header['Content-Length']
394
- page_as_string = @mech.get_file("http://localhost/frame_test.html")
395
- assert_equal(content_length.to_i, page_as_string.length.to_i)
396
- end
397
-
398
391
  def test_get_follow_meta_refresh
399
392
  @mech.follow_meta_refresh = true
400
393
 
@@ -696,6 +689,21 @@ but not <a href="/" rel="me nofollow">this</a>!
696
689
  assert_equal('File Upload Form', pages.title)
697
690
  end
698
691
 
692
+ def test_get_file
693
+ body = @mech.get_file 'http://localhost/frame_test.html'
694
+
695
+ assert_kind_of String, body
696
+ refute_empty body
697
+ end
698
+
699
+ def test_get_file_download
700
+ # non-Mechanize::File
701
+ body = @mech.get_file 'http://localhost/button.jpg'
702
+
703
+ assert_kind_of String, body
704
+ refute_empty body
705
+ end
706
+
699
707
  def test_head
700
708
  page = @mech.head('http://localhost/verb', { 'q' => 'foo' })
701
709
  assert_equal 0, @mech.history.length
@@ -179,14 +179,46 @@ class TestMechanizeCookie < Mechanize::TestCase
179
179
  assert !cookie.for_domain?
180
180
  end
181
181
 
182
- def test_parse_expires_session
183
- cookie = 'PRETANET=TGIAqbFXtt; Name=/PRETANET; Path=/; Max-Age=1.2; Content-type=text/html; Domain=192.168.6.196; expires=;'
182
+ def test_parse_max_age
183
+ url = URI.parse('http://localhost/')
184
+
185
+ date = 'Mon, 19 Feb 2012 19:26:04 GMT'
186
+
187
+ cookie = Mechanize::Cookie.parse(url, "name=Akinori; expires=#{date}").first
188
+ assert_equal Time.at(1329679564), cookie.expires
189
+
190
+ cookie = Mechanize::Cookie.parse(url, 'name=Akinori; max-age=3600').first
191
+ assert_in_delta Time.now + 3600, cookie.expires, 1
192
+
193
+ # Max-Age has precedence over Expires
194
+ cookie = Mechanize::Cookie.parse(url, "name=Akinori; max-age=3600; expires=#{date}").first
195
+ assert_in_delta Time.now + 3600, cookie.expires, 1
196
+
197
+ cookie = Mechanize::Cookie.parse(url, "name=Akinori; expires=#{date}; max-age=3600").first
198
+ assert_in_delta Time.now + 3600, cookie.expires, 1
199
+ end
184
200
 
201
+ def test_parse_expires_session
185
202
  url = URI.parse('http://localhost/')
186
203
 
187
- cookie = Mechanize::Cookie.parse(url, cookie).first
204
+ [
205
+ 'name=Akinori',
206
+ 'name=Akinori; expires',
207
+ 'name=Akinori; max-age',
208
+ 'name=Akinori; expires=',
209
+ 'name=Akinori; max-age=',
210
+ ].each { |str|
211
+ cookie = Mechanize::Cookie.parse(url, str).first
212
+ assert cookie.session, str
213
+ }
188
214
 
189
- assert cookie.session
215
+ [
216
+ 'name=Akinori; expires=Mon, 19 Feb 2012 19:26:04 GMT',
217
+ 'name=Akinori; max-age=3600',
218
+ ].each { |str|
219
+ cookie = Mechanize::Cookie.parse(url, str).first
220
+ assert !cookie.session, str
221
+ }
190
222
  end
191
223
 
192
224
  def test_parse_many
@@ -198,10 +230,15 @@ class TestMechanizeCookie < Mechanize::TestCase
198
230
  "name=Aaron; Domain=localhost; Expires=Sun, 06 Nov 2011 00:29:51 GMT; Path=/; HttpOnly, " \
199
231
  "expired=doh; Expires=Fri, 04 Nov 2011 00:29:51 GMT; Path=/, " \
200
232
  "a_path=some_path; Expires=Sun, 06 Nov 2011 00:29:51 GMT; Path=/some_path, " \
201
- "no_path=no_path; Expires=Sun, 06 Nov 2011 00:29:51 GMT, no_expires=nope; Path=/"
233
+ "no_path1=no_path; Expires=Sun, 06 Nov 2011 00:29:52 GMT, no_expires=nope; Path=/, " \
234
+ "no_path2=no_path; Expires=Sun, 06 Nov 2011 00:29:52 GMT; no_expires=nope; Path, " \
235
+ "no_path3=no_path; Expires=Sun, 06 Nov 2011 00:29:52 GMT; no_expires=nope; Path=, " \
236
+ "no_domain1=no_domain; Expires=Sun, 06 Nov 2011 00:29:53 GMT; no_expires=nope, " \
237
+ "no_domain2=no_domain; Expires=Sun, 06 Nov 2011 00:29:53 GMT; no_expires=nope; Domain, " \
238
+ "no_domain3=no_domain; Expires=Sun, 06 Nov 2011 00:29:53 GMT; no_expires=nope; Domain="
202
239
 
203
240
  cookies = Mechanize::Cookie.parse url, cookie_str
204
- assert_equal 8, cookies.length
241
+ assert_equal 13, cookies.length
205
242
 
206
243
  name = cookies.find { |c| c.name == 'name' }
207
244
  assert_equal "Aaron", name.value
@@ -218,10 +255,20 @@ class TestMechanizeCookie < Mechanize::TestCase
218
255
  assert_equal "/", no_expires.path
219
256
  assert_nil no_expires.expires
220
257
 
221
- no_path = cookies.find { |c| c.name == 'no_path' }
222
- assert_equal "no_path", no_path.value
223
- assert_equal "/", no_path.path
224
- assert_equal Time.at(1320539391), no_path.expires
258
+ no_path_cookies = cookies.select { |c| c.value == 'no_path' }
259
+ assert_equal 3, no_path_cookies.size
260
+ no_path_cookies.each { |c|
261
+ assert_equal "/", c.path, c.name
262
+ assert_equal Time.at(1320539392), c.expires, c.name
263
+ }
264
+
265
+ no_domain_cookies = cookies.select { |c| c.value == 'no_domain' }
266
+ assert_equal 3, no_domain_cookies.size
267
+ no_domain_cookies.each { |c|
268
+ assert !c.for_domain?, c.name
269
+ assert_equal c.domain, url.host, c.name
270
+ assert_equal Time.at(1320539393), c.expires, c.name
271
+ }
225
272
 
226
273
  assert cookies.find { |c| c.name == 'expired' }
227
274
  end
@@ -8,6 +8,16 @@ class TestMechanizeDownload < Mechanize::TestCase
8
8
  @parser = Mechanize::Download
9
9
  end
10
10
 
11
+ def test_body
12
+ uri = URI.parse 'http://example/foo.html'
13
+ body_io = StringIO.new '0123456789'
14
+
15
+ download = @parser.new uri, nil, body_io
16
+
17
+ assert_equal '0123456789', download.body
18
+ assert_equal 0, download.body_io.pos
19
+ end
20
+
11
21
  def test_save_string_io
12
22
  uri = URI.parse 'http://example/foo.html'
13
23
  body_io = StringIO.new '0123456789'
@@ -31,6 +31,69 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
31
31
  realm
32
32
  end
33
33
 
34
+ def test_auto_io
35
+ Tempfile.open 'input' do |input_io|
36
+ input_io.binmode
37
+ input_io.write '12345'
38
+ input_io.rewind
39
+
40
+ out_io = @agent.auto_io __name__, 1024, input_io
41
+
42
+ assert_equal '12345', out_io.string
43
+
44
+ assert_equal Encoding::BINARY, out_io.string.encoding if
45
+ Object.const_defined? :Encoding
46
+ end
47
+ end
48
+
49
+ def test_auto_io_chunk
50
+ Tempfile.open 'input' do |input_io|
51
+ chunks = []
52
+
53
+ input_io.binmode
54
+ input_io.write '12345'
55
+ input_io.rewind
56
+
57
+ @agent.auto_io __name__, 1, input_io do |chunk|
58
+ chunks << chunk
59
+ end
60
+
61
+ assert_equal %w[1 2 3 4 5], chunks
62
+ end
63
+ end
64
+
65
+ def test_auto_io_tempfile
66
+ @agent.max_file_buffer = 3
67
+
68
+ Tempfile.open 'input' do |input_io|
69
+ input_io.binmode
70
+ input_io.write '12345'
71
+ input_io.rewind
72
+
73
+ out_io = @agent.auto_io __name__, 1, input_io
74
+
75
+ result = out_io.read
76
+ assert_equal '12345', result
77
+
78
+ assert_equal Encoding::BINARY, result.encoding if
79
+ Object.const_defined? :Encoding
80
+ end
81
+ end
82
+
83
+ def test_auto_io_yield
84
+ Tempfile.open 'input' do |input_io|
85
+ input_io.binmode
86
+ input_io.write '12345'
87
+ input_io.rewind
88
+
89
+ out_io = @agent.auto_io __name__, 1024, input_io do |chunk|
90
+ "x#{chunk}"
91
+ end
92
+
93
+ assert_equal 'x12345', out_io.string
94
+ end
95
+ end
96
+
34
97
  def test_certificate_equals
35
98
  cert_path = File.expand_path '../data/server.crt', __FILE__
36
99
  cert = OpenSSL::X509::Certificate.new File.read cert_path
@@ -176,8 +239,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
176
239
  @agent.follow_meta_refresh = true
177
240
  @agent.follow_meta_refresh_self = true
178
241
 
179
- page = Mechanize::Page.new(@uri, {'content-type' => 'text/html'}, '',
180
- 200, @mech)
242
+ page = Mechanize::Page.new(@uri, nil, '', 200, @mech)
181
243
  @res.instance_variable_set :@header, 'refresh' => ['0']
182
244
 
183
245
  refresh = @agent.get_meta_refresh @res, @uri, page
@@ -186,8 +248,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
186
248
  end
187
249
 
188
250
  def test_get_meta_refresh_header_no_follow
189
- page = Mechanize::Page.new(@uri, {'content-type' => 'text/html'}, '',
190
- 200, @mech)
251
+ page = Mechanize::Page.new(@uri, nil, '', 200, @mech)
191
252
  @res.instance_variable_set :@header, 'refresh' => ['0']
192
253
 
193
254
  refresh = @agent.get_meta_refresh @res, @uri, page
@@ -198,8 +259,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
198
259
  def test_get_meta_refresh_header_no_follow_self
199
260
  @agent.follow_meta_refresh = true
200
261
 
201
- page = Mechanize::Page.new(@uri, {'content-type' => 'text/html'}, '',
202
- 200, @mech)
262
+ page = Mechanize::Page.new(@uri, nil, '', 200, @mech)
203
263
  @res.instance_variable_set :@header, 'refresh' => ['0']
204
264
 
205
265
  refresh = @agent.get_meta_refresh @res, @uri, page
@@ -216,8 +276,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
216
276
  <meta http-equiv="refresh" content="0">
217
277
  BODY
218
278
 
219
- page = Mechanize::Page.new(@uri, {'content-type' => 'text/html'}, body,
220
- 200, @mech)
279
+ page = Mechanize::Page.new(@uri, nil, body, 200, @mech)
221
280
 
222
281
  refresh = @agent.get_meta_refresh @res, @uri, page
223
282
 
@@ -230,8 +289,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
230
289
  <meta http-equiv="refresh" content="0">
231
290
  BODY
232
291
 
233
- page = Mechanize::Page.new(@uri, {'content-type' => 'text/html'}, body,
234
- 200, @mech)
292
+ page = Mechanize::Page.new(@uri, nil, body, 200, @mech)
235
293
 
236
294
  refresh = @agent.get_meta_refresh @res, @uri, page
237
295
 
@@ -246,8 +304,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
246
304
  <meta http-equiv="refresh" content="0">
247
305
  BODY
248
306
 
249
- page = Mechanize::Page.new(@uri, {'content-type' => 'text/html'}, body,
250
- 200, @mech)
307
+ page = Mechanize::Page.new(@uri, nil, body, 200, @mech)
251
308
 
252
309
  refresh = @agent.get_meta_refresh @res, @uri, page
253
310
 
@@ -301,6 +358,14 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
301
358
  assert_equal 1, @agent.http.idle_timeout
302
359
  end
303
360
 
361
+ def test_inflate
362
+ body_io = StringIO.new "x\x9C+H,*\x01\x00\x04?\x01\xB8"
363
+
364
+ result = @agent.inflate body_io
365
+
366
+ assert_equal 'part', result.read
367
+ end
368
+
304
369
  def test_post_connect
305
370
  @agent.post_connect_hooks << proc { |agent, uri, response, body|
306
371
  assert_equal @agent, agent
@@ -716,6 +781,8 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
716
781
  body = @agent.response_content_encoding @res, body_io
717
782
 
718
783
  assert_equal 'part', body.read
784
+
785
+ assert body_io.closed?
719
786
  end
720
787
 
721
788
  def test_response_content_encoding_deflate_chunked
@@ -737,6 +804,8 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
737
804
 
738
805
  assert_match %r%error handling content-encoding deflate:%, e.message
739
806
  assert_match %r%Zlib%, e.message
807
+
808
+ assert body_io.closed?
740
809
  end
741
810
 
742
811
  def test_response_content_encoding_deflate_empty
@@ -764,6 +833,8 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
764
833
  body = @agent.response_content_encoding @res, body_io
765
834
 
766
835
  assert_equal 'part', body.read
836
+
837
+ assert body_io.closed?
767
838
  end
768
839
 
769
840
  def test_response_content_encoding_gzip_chunked
@@ -795,6 +866,8 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
795
866
 
796
867
  assert_match %r%unable to gunzip response, trying raw inflate%, log.string
797
868
  assert_match %r%unable to gunzip response:%, log.string
869
+
870
+ assert body_io.closed?
798
871
  end
799
872
 
800
873
  def test_response_content_encoding_gzip_corrupt_checksum
@@ -958,8 +1031,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
958
1031
  <meta http-equiv="refresh" content="0">
959
1032
  BODY
960
1033
 
961
- page = Mechanize::Page.new(uri, {'content-type' => 'text/html'}, body,
962
- 200, @mech)
1034
+ page = Mechanize::Page.new(uri, nil, body, 200, @mech)
963
1035
 
964
1036
  @agent.follow_meta_refresh = true
965
1037
  @agent.follow_meta_refresh_self = true
@@ -977,8 +1049,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
977
1049
  <meta http-equiv="refresh" content="0">
978
1050
  BODY
979
1051
 
980
- page = Mechanize::Page.new(uri, {'content-type' => 'text/html'}, body,
981
- 200, @mech)
1052
+ page = Mechanize::Page.new(uri, nil, body, 200, @mech)
982
1053
 
983
1054
  @agent.follow_meta_refresh = true
984
1055
  @agent.follow_meta_refresh_self = true
@@ -1159,6 +1230,8 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1159
1230
  end
1160
1231
 
1161
1232
  def test_response_read_large
1233
+ @agent.max_file_buffer = 10240
1234
+
1162
1235
  def @res.read_body() yield 'a' * 10241 end
1163
1236
  def @res.content_length() 10241 end
1164
1237
 
@@ -1169,6 +1242,8 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1169
1242
  end
1170
1243
 
1171
1244
  def test_response_read_large_chunked
1245
+ @agent.max_file_buffer = 10240
1246
+
1172
1247
  def @res.read_body
1173
1248
  11.times do yield 'a' * 1024 end
1174
1249
  end
@@ -1363,6 +1438,19 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1363
1438
  end
1364
1439
  end
1365
1440
 
1441
+ def test_use_tempfile_eh
1442
+ refute @agent.use_tempfile? nil
1443
+
1444
+ @agent.max_file_buffer = 1
1445
+
1446
+ refute @agent.use_tempfile? 0
1447
+ assert @agent.use_tempfile? 1
1448
+
1449
+ @agent.max_file_buffer = nil
1450
+
1451
+ refute @agent.use_tempfile? 1
1452
+ end
1453
+
1366
1454
  def test_verify_none_equals
1367
1455
  @agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
1368
1456
 
@@ -8,13 +8,43 @@ class TestMechanizePage < Mechanize::TestCase
8
8
  @uri = URI 'http://example/'
9
9
  end
10
10
 
11
- def test_initialize_bad_content_type
12
- e = assert_raises Mechanize::ContentTypeError do
13
- Mechanize::Page.new(URI('http://example/'),
14
- { 'content-type' => 'text/xml' }, 'hello', '200')
15
- end
11
+ def test_initialize_good_content_type
12
+ page = Mechanize::Page.new
13
+ assert_equal('text/html', page.content_type)
14
+
15
+ [
16
+ 'text/html',
17
+ 'Text/HTML',
18
+ 'text/html; charset=UTF-8',
19
+ 'text/html ; charset=US-ASCII',
20
+ 'application/xhtml+xml',
21
+ 'Application/XHTML+XML',
22
+ 'application/xhtml+xml; charset=UTF-8',
23
+ 'application/xhtml+xml ; charset=US-ASCII',
24
+ ].each { |content_type|
25
+ page = Mechanize::Page.new(URI('http://example/'),
26
+ { 'content-type' => content_type }, 'hello', '200')
27
+
28
+ assert_equal(content_type, page.content_type, content_type)
29
+ }
30
+ end
16
31
 
17
- assert_equal('text/xml', e.content_type)
32
+ def test_initialize_bad_content_type
33
+ [
34
+ 'text/xml',
35
+ 'text/xhtml',
36
+ 'text/htmlfu',
37
+ 'footext/html',
38
+ 'application/xhtml+xmlfu',
39
+ 'fooapplication/xhtml+xml',
40
+ ].each { |content_type|
41
+ e = assert_raises(Mechanize::ContentTypeError, content_type) do
42
+ Mechanize::Page.new(URI('http://example/'),
43
+ { 'content-type' => content_type }, 'hello', '200')
44
+ end
45
+
46
+ assert_equal(content_type, e.content_type, content_type)
47
+ }
18
48
  end
19
49
 
20
50
  def test_frames
@@ -8,8 +8,7 @@ class TestMechanizePageImage < Mechanize::TestCase
8
8
  @uri = URI 'http://example/'
9
9
  @src = (@uri + 'a.jpg').to_s
10
10
 
11
- @empty_page = Mechanize::Page.new(@uri, { 'content-type' => 'text/html' },
12
- '', 200, @mech)
11
+ @empty_page = Mechanize::Page.new(@uri, nil, '', 200, @mech)
13
12
  end
14
13
 
15
14
  def img attributes
@@ -15,8 +15,7 @@ class TestMechanizePageMetaRefresh < Mechanize::TestCase
15
15
  <head><meta http-equiv="refresh" content="#{delay};url=#{uri}"></head>
16
16
  BODY
17
17
 
18
- Mechanize::Page.new(@uri, { 'content-type' => 'text/html' }, body, 200,
19
- @mech)
18
+ Mechanize::Page.new(@uri, nil, body, 200, @mech)
20
19
  end
21
20
 
22
21
  def util_meta_refresh page
@@ -126,8 +125,7 @@ class TestMechanizePageMetaRefresh < Mechanize::TestCase
126
125
  <head><meta http-equiv="refresh"></head>
127
126
  BODY
128
127
 
129
- page = Mechanize::Page.new(@uri, { 'content-type' => 'text/html' }, body,
130
- 200, @mech)
128
+ page = Mechanize::Page.new(@uri, nil, body, 200, @mech)
131
129
 
132
130
  assert_nil util_meta_refresh page
133
131
  end
@@ -137,8 +135,7 @@ class TestMechanizePageMetaRefresh < Mechanize::TestCase
137
135
  <head><meta http-equiv="other-thing" content="0;"></head>
138
136
  BODY
139
137
 
140
- page = Mechanize::Page.new(@uri, { 'content-type' => 'text/html' }, body,
141
- 200, @mech)
138
+ page = Mechanize::Page.new(@uri, nil, body, 200, @mech)
142
139
 
143
140
  assert_nil util_meta_refresh page
144
141
  end
metadata CHANGED
@@ -5,9 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
- - 2
9
- - 1
10
- version: 2.2.1
8
+ - 3
9
+ version: "2.3"
11
10
  platform: ruby
12
11
  authors:
13
12
  - Eric Hodel
@@ -39,7 +38,7 @@ cert_chain:
39
38
  YJY7T/W2n+eWy8WuPhzVUkyzguj0bQe27NDeabgCh2mHd4Hynk2AkYh8MQ==
40
39
  -----END CERTIFICATE-----
41
40
 
42
- date: 2012-02-14 00:00:00 Z
41
+ date: 2012-02-21 00:00:00 Z
43
42
  dependencies:
44
43
  - !ruby/object:Gem::Dependency
45
44
  name: net-http-digest_auth
metadata.gz.sig CHANGED
Binary file