tenderlove-mechanize 0.9.3.20090623142847 → 0.9.3.20090911221705
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +55 -48
- data/Rakefile +12 -22
- data/lib/mechanize.rb +618 -4
- data/lib/mechanize/chain.rb +33 -0
- data/lib/mechanize/chain/auth_headers.rb +78 -0
- data/lib/mechanize/chain/body_decoding_handler.rb +46 -0
- data/lib/mechanize/chain/connection_resolver.rb +76 -0
- data/lib/mechanize/chain/custom_headers.rb +21 -0
- data/lib/{www/mechanize → mechanize}/chain/handler.rb +1 -1
- data/lib/mechanize/chain/header_resolver.rb +51 -0
- data/lib/mechanize/chain/parameter_resolver.rb +22 -0
- data/lib/{www/mechanize → mechanize}/chain/post_connect_hook.rb +0 -0
- data/lib/mechanize/chain/pre_connect_hook.rb +20 -0
- data/lib/mechanize/chain/request_resolver.rb +30 -0
- data/lib/mechanize/chain/response_body_parser.rb +38 -0
- data/lib/mechanize/chain/response_header_handler.rb +48 -0
- data/lib/mechanize/chain/response_reader.rb +39 -0
- data/lib/mechanize/chain/ssl_resolver.rb +40 -0
- data/lib/mechanize/chain/uri_resolver.rb +75 -0
- data/lib/mechanize/content_type_error.rb +14 -0
- data/lib/mechanize/cookie.rb +70 -0
- data/lib/mechanize/cookie_jar.rb +188 -0
- data/lib/mechanize/file.rb +71 -0
- data/lib/mechanize/file_response.rb +60 -0
- data/lib/mechanize/file_saver.rb +37 -0
- data/lib/mechanize/form.rb +378 -0
- data/lib/mechanize/form/button.rb +9 -0
- data/lib/mechanize/form/check_box.rb +11 -0
- data/lib/mechanize/form/field.rb +30 -0
- data/lib/mechanize/form/file_upload.rb +22 -0
- data/lib/mechanize/form/image_button.rb +21 -0
- data/lib/mechanize/form/multi_select_list.rb +67 -0
- data/lib/mechanize/form/option.rb +49 -0
- data/lib/mechanize/form/radio_button.rb +49 -0
- data/lib/mechanize/form/select_list.rb +43 -0
- data/lib/mechanize/headers.rb +11 -0
- data/lib/mechanize/history.rb +65 -0
- data/lib/mechanize/inspect.rb +88 -0
- data/lib/{www/mechanize → mechanize}/monkey_patch.rb +4 -6
- data/lib/mechanize/page.rb +206 -0
- data/lib/mechanize/page/base.rb +8 -0
- data/lib/mechanize/page/frame.rb +20 -0
- data/lib/mechanize/page/image.rb +26 -0
- data/lib/mechanize/page/label.rb +20 -0
- data/lib/mechanize/page/link.rb +48 -0
- data/lib/mechanize/page/meta.rb +50 -0
- data/lib/mechanize/pluggable_parsers.rb +101 -0
- data/lib/mechanize/redirect_limit_reached_error.rb +16 -0
- data/lib/mechanize/redirect_not_get_or_head_error.rb +18 -0
- data/lib/mechanize/response_code_error.rb +22 -0
- data/lib/mechanize/unsupported_scheme_error.rb +8 -0
- data/lib/mechanize/util.rb +67 -0
- data/mechanize.gemspec +8 -8
- data/test/chain/test_argument_validator.rb +2 -2
- data/test/chain/test_auth_headers.rb +2 -2
- data/test/chain/test_custom_headers.rb +2 -2
- data/test/chain/test_header_resolver.rb +3 -3
- data/test/chain/test_parameter_resolver.rb +4 -4
- data/test/chain/test_request_resolver.rb +4 -4
- data/test/chain/test_response_reader.rb +3 -3
- data/test/helper.rb +1 -1
- data/test/htdocs/tc_bad_charset.html +9 -0
- data/test/htdocs/tc_charset.html +6 -0
- data/test/htdocs/test_bad_encoding.html +52 -0
- data/test/test_authenticate.rb +3 -3
- data/test/test_bad_links.rb +1 -1
- data/test/test_blank_form.rb +1 -1
- data/test/test_checkboxes.rb +1 -1
- data/test/test_content_type.rb +2 -2
- data/test/test_cookie_class.rb +12 -12
- data/test/test_cookie_jar.rb +13 -13
- data/test/test_cookies.rb +1 -1
- data/test/test_encoded_links.rb +1 -1
- data/test/test_errors.rb +2 -2
- data/test/test_follow_meta.rb +3 -3
- data/test/test_form_action.rb +1 -1
- data/test/test_form_as_hash.rb +1 -1
- data/test/test_form_button.rb +2 -2
- data/test/test_form_no_inputname.rb +1 -1
- data/test/test_forms.rb +1 -1
- data/test/test_frames.rb +1 -1
- data/test/test_get_headers.rb +1 -1
- data/test/test_gzipping.rb +2 -2
- data/test/test_hash_api.rb +1 -1
- data/test/test_history.rb +7 -7
- data/test/test_history_added.rb +1 -1
- data/test/test_html_unscape_forms.rb +7 -7
- data/test/test_if_modified_since.rb +1 -1
- data/test/test_keep_alive.rb +1 -1
- data/test/test_links.rb +2 -2
- data/test/test_mech.rb +2 -2
- data/test/test_mechanize_file.rb +7 -7
- data/test/test_meta.rb +2 -2
- data/test/test_multi_select.rb +1 -1
- data/test/test_no_attributes.rb +1 -1
- data/test/test_option.rb +1 -1
- data/test/test_page.rb +3 -3
- data/test/test_pluggable_parser.rb +14 -14
- data/test/test_post_form.rb +1 -1
- data/test/test_pretty_print.rb +2 -2
- data/test/test_radiobutton.rb +1 -1
- data/test/test_redirect_limit_reached.rb +1 -3
- data/test/test_redirect_verb_handling.rb +1 -3
- data/test/test_referer.rb +1 -1
- data/test/test_relative_links.rb +1 -1
- data/test/test_request.rb +1 -1
- data/test/test_response_code.rb +3 -3
- data/test/test_save_file.rb +3 -3
- data/test/test_scheme.rb +3 -3
- data/test/test_select.rb +2 -2
- data/test/test_select_all.rb +1 -1
- data/test/test_select_none.rb +1 -1
- data/test/test_select_noopts.rb +1 -1
- data/test/test_set_fields.rb +1 -1
- data/test/test_ssl_server.rb +1 -1
- data/test/test_subclass.rb +1 -1
- data/test/test_textarea.rb +1 -1
- data/test/test_upload.rb +1 -1
- data/test/test_verbs.rb +1 -1
- metadata +61 -56
- data/lib/www/mechanize.rb +0 -619
- data/lib/www/mechanize/chain.rb +0 -34
- data/lib/www/mechanize/chain/auth_headers.rb +0 -80
- data/lib/www/mechanize/chain/body_decoding_handler.rb +0 -48
- data/lib/www/mechanize/chain/connection_resolver.rb +0 -78
- data/lib/www/mechanize/chain/custom_headers.rb +0 -23
- data/lib/www/mechanize/chain/header_resolver.rb +0 -53
- data/lib/www/mechanize/chain/parameter_resolver.rb +0 -24
- data/lib/www/mechanize/chain/pre_connect_hook.rb +0 -22
- data/lib/www/mechanize/chain/request_resolver.rb +0 -32
- data/lib/www/mechanize/chain/response_body_parser.rb +0 -40
- data/lib/www/mechanize/chain/response_header_handler.rb +0 -50
- data/lib/www/mechanize/chain/response_reader.rb +0 -41
- data/lib/www/mechanize/chain/ssl_resolver.rb +0 -42
- data/lib/www/mechanize/chain/uri_resolver.rb +0 -77
- data/lib/www/mechanize/content_type_error.rb +0 -16
- data/lib/www/mechanize/cookie.rb +0 -72
- data/lib/www/mechanize/cookie_jar.rb +0 -191
- data/lib/www/mechanize/file.rb +0 -73
- data/lib/www/mechanize/file_response.rb +0 -62
- data/lib/www/mechanize/file_saver.rb +0 -39
- data/lib/www/mechanize/form.rb +0 -360
- data/lib/www/mechanize/form/button.rb +0 -8
- data/lib/www/mechanize/form/check_box.rb +0 -13
- data/lib/www/mechanize/form/field.rb +0 -28
- data/lib/www/mechanize/form/file_upload.rb +0 -24
- data/lib/www/mechanize/form/image_button.rb +0 -23
- data/lib/www/mechanize/form/multi_select_list.rb +0 -69
- data/lib/www/mechanize/form/option.rb +0 -51
- data/lib/www/mechanize/form/radio_button.rb +0 -38
- data/lib/www/mechanize/form/select_list.rb +0 -45
- data/lib/www/mechanize/headers.rb +0 -12
- data/lib/www/mechanize/history.rb +0 -67
- data/lib/www/mechanize/inspect.rb +0 -90
- data/lib/www/mechanize/page.rb +0 -181
- data/lib/www/mechanize/page/base.rb +0 -10
- data/lib/www/mechanize/page/frame.rb +0 -22
- data/lib/www/mechanize/page/link.rb +0 -50
- data/lib/www/mechanize/page/meta.rb +0 -51
- data/lib/www/mechanize/pluggable_parsers.rb +0 -103
- data/lib/www/mechanize/redirect_limit_reached_error.rb +0 -18
- data/lib/www/mechanize/redirect_not_get_or_head_error.rb +0 -20
- data/lib/www/mechanize/response_code_error.rb +0 -25
- data/lib/www/mechanize/unsupported_scheme_error.rb +0 -10
- data/lib/www/mechanize/util.rb +0 -76
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'mechanize/chain/handler'
|
2
|
+
require 'mechanize/chain/uri_resolver'
|
3
|
+
require 'mechanize/chain/parameter_resolver'
|
4
|
+
require 'mechanize/chain/request_resolver'
|
5
|
+
require 'mechanize/chain/custom_headers'
|
6
|
+
require 'mechanize/chain/connection_resolver'
|
7
|
+
require 'mechanize/chain/ssl_resolver'
|
8
|
+
require 'mechanize/chain/pre_connect_hook'
|
9
|
+
require 'mechanize/chain/auth_headers'
|
10
|
+
require 'mechanize/chain/header_resolver'
|
11
|
+
require 'mechanize/chain/response_body_parser'
|
12
|
+
require 'mechanize/chain/response_header_handler'
|
13
|
+
require 'mechanize/chain/response_reader'
|
14
|
+
require 'mechanize/chain/body_decoding_handler'
|
15
|
+
|
16
|
+
class Mechanize
|
17
|
+
class Chain
|
18
|
+
def initialize(list)
|
19
|
+
@list = list
|
20
|
+
@list.each { |l| l.chain = self }
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle(request)
|
24
|
+
@list.first.handle(self, request)
|
25
|
+
end
|
26
|
+
|
27
|
+
def pass(obj, request)
|
28
|
+
next_link = @list[@list.index(obj) + 1]
|
29
|
+
next_link.handle(self, request) if next_link
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class AuthHeaders
|
4
|
+
include Mechanize::Handler
|
5
|
+
|
6
|
+
@@nonce_count = Hash.new(0)
|
7
|
+
CNONCE = Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
|
8
|
+
|
9
|
+
def initialize(auth_hash, user, password, digest)
|
10
|
+
@auth_hash = auth_hash
|
11
|
+
@user = user
|
12
|
+
@password = password
|
13
|
+
@digest = digest
|
14
|
+
end
|
15
|
+
|
16
|
+
def handle(ctx, params)
|
17
|
+
uri = params[:uri]
|
18
|
+
request = params[:request]
|
19
|
+
|
20
|
+
if( @auth_hash[uri.host] )
|
21
|
+
case @auth_hash[uri.host]
|
22
|
+
when :basic
|
23
|
+
request.basic_auth(@user, @password)
|
24
|
+
when :iis_digest
|
25
|
+
digest_response = self.gen_auth_header(uri,request, @digest, true)
|
26
|
+
request['Authorization'] = digest_response
|
27
|
+
when :digest
|
28
|
+
if @digest
|
29
|
+
digest_response = self.gen_auth_header(uri,request, @digest)
|
30
|
+
request['Authorization'] = digest_response
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def gen_auth_header(uri, request, auth_header, is_IIS = false)
|
38
|
+
auth_header =~ /^(\w+) (.*)/
|
39
|
+
|
40
|
+
params = {}
|
41
|
+
$2.gsub(/(\w+)=("[^"]*"|[^,]*)/) {
|
42
|
+
params[$1] = $2.gsub(/^"/, '').gsub(/"$/, '')
|
43
|
+
}
|
44
|
+
|
45
|
+
@@nonce_count[params['nonce']] += 1
|
46
|
+
|
47
|
+
a_1 = "#{@user}:#{params['realm']}:#{@password}"
|
48
|
+
a_2 = "#{request.method}:#{uri.path}"
|
49
|
+
request_digest = ''
|
50
|
+
request_digest << Digest::MD5.hexdigest(a_1)
|
51
|
+
request_digest << ':' << params['nonce']
|
52
|
+
request_digest << ':' << ('%08x' % @@nonce_count[params['nonce']])
|
53
|
+
request_digest << ':' << CNONCE
|
54
|
+
request_digest << ':' << params['qop']
|
55
|
+
request_digest << ':' << Digest::MD5.hexdigest(a_2)
|
56
|
+
|
57
|
+
header = ''
|
58
|
+
header << "Digest username=\"#{@user}\", "
|
59
|
+
if is_IIS then
|
60
|
+
header << "qop=\"#{params['qop']}\", "
|
61
|
+
else
|
62
|
+
header << "qop=#{params['qop']}, "
|
63
|
+
end
|
64
|
+
header << "uri=\"#{uri.path}\", "
|
65
|
+
header << %w{ algorithm opaque nonce realm }.map { |field|
|
66
|
+
next unless params[field]
|
67
|
+
"#{field}=\"#{params[field]}\""
|
68
|
+
}.compact.join(', ')
|
69
|
+
|
70
|
+
header << ", nc=#{'%08x' % @@nonce_count[params['nonce']]}, "
|
71
|
+
header << "cnonce=\"#{CNONCE}\", "
|
72
|
+
header << "response=\"#{Digest::MD5.hexdigest(request_digest)}\""
|
73
|
+
|
74
|
+
return header
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class BodyDecodingHandler
|
4
|
+
include Mechanize::Handler
|
5
|
+
|
6
|
+
def handle(ctx, options)
|
7
|
+
body = options[:response_body]
|
8
|
+
response = options[:response]
|
9
|
+
|
10
|
+
options[:response_body] =
|
11
|
+
if encoding = response['Content-Encoding']
|
12
|
+
case encoding.downcase
|
13
|
+
when 'gzip'
|
14
|
+
Mechanize.log.debug('gunzip body') if Mechanize.log
|
15
|
+
if response['Content-Length'].to_i > 0 || body.length > 0
|
16
|
+
begin
|
17
|
+
Zlib::GzipReader.new(body).read
|
18
|
+
rescue Zlib::BufError, Zlib::GzipFile::Error
|
19
|
+
if Mechanize.log
|
20
|
+
Mechanize.log.error('Caught a Zlib::BufError')
|
21
|
+
end
|
22
|
+
body.rewind
|
23
|
+
body.read(10)
|
24
|
+
Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(body.read)
|
25
|
+
rescue Zlib::DataError
|
26
|
+
if Mechanize.log
|
27
|
+
Mechanize.log.error("Caught a Zlib::DataError, unable to decode page: #{$!.to_s}")
|
28
|
+
end
|
29
|
+
''
|
30
|
+
end
|
31
|
+
else
|
32
|
+
''
|
33
|
+
end
|
34
|
+
when 'x-gzip'
|
35
|
+
body.read
|
36
|
+
else
|
37
|
+
raise 'Unsupported content encoding'
|
38
|
+
end
|
39
|
+
else
|
40
|
+
body.read
|
41
|
+
end
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class ConnectionResolver
|
4
|
+
include Mechanize::Handler
|
5
|
+
|
6
|
+
def initialize( connection_cache,
|
7
|
+
keep_alive,
|
8
|
+
proxy_addr,
|
9
|
+
proxy_port,
|
10
|
+
proxy_user,
|
11
|
+
proxy_pass )
|
12
|
+
|
13
|
+
@connection_cache = connection_cache
|
14
|
+
@keep_alive = keep_alive
|
15
|
+
@proxy_addr = proxy_addr
|
16
|
+
@proxy_port = proxy_port
|
17
|
+
@proxy_user = proxy_user
|
18
|
+
@proxy_pass = proxy_pass
|
19
|
+
end
|
20
|
+
|
21
|
+
def handle(ctx, params)
|
22
|
+
uri = params[:uri]
|
23
|
+
http_obj = nil
|
24
|
+
|
25
|
+
case uri.scheme.downcase
|
26
|
+
when 'http', 'https'
|
27
|
+
cache_obj = (@connection_cache["#{uri.host}:#{uri.port}"] ||= {
|
28
|
+
:connection => nil,
|
29
|
+
:keep_alive_options => {},
|
30
|
+
})
|
31
|
+
http_obj = cache_obj[:connection]
|
32
|
+
if http_obj.nil? || ! http_obj.started?
|
33
|
+
http_obj = cache_obj[:connection] =
|
34
|
+
Net::HTTP.new( uri.host,
|
35
|
+
uri.port,
|
36
|
+
@proxy_addr,
|
37
|
+
@proxy_port,
|
38
|
+
@proxy_user,
|
39
|
+
@proxy_pass
|
40
|
+
)
|
41
|
+
cache_obj[:keep_alive_options] = {}
|
42
|
+
end
|
43
|
+
|
44
|
+
# If we're keeping connections alive and the last request time is too
|
45
|
+
# long ago, stop the connection. Or, if the max requests left is 1,
|
46
|
+
# reset the connection.
|
47
|
+
if @keep_alive && http_obj.started?
|
48
|
+
opts = cache_obj[:keep_alive_options]
|
49
|
+
if((opts[:timeout] &&
|
50
|
+
Time.now.to_i - cache_obj[:last_request_time] > opts[:timeout].to_i) ||
|
51
|
+
opts[:max] && opts[:max].to_i == 1)
|
52
|
+
|
53
|
+
Mechanize.log.debug('Finishing stale connection') if Mechanize.log
|
54
|
+
http_obj.finish
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
cache_obj[:last_request_time] = Time.now.to_i
|
60
|
+
when 'file'
|
61
|
+
http_obj = Object.new
|
62
|
+
class << http_obj
|
63
|
+
def started?; true; end
|
64
|
+
def request(request, *args, &block)
|
65
|
+
response = FileResponse.new(request.uri.path)
|
66
|
+
yield response
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
params[:connection] = http_obj
|
72
|
+
super
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class CustomHeaders
|
4
|
+
include Mechanize::Handler
|
5
|
+
|
6
|
+
def handle(ctx, params)
|
7
|
+
request = params[:request]
|
8
|
+
params[:headers].each do |k,v|
|
9
|
+
case k
|
10
|
+
when :etag then request["ETag"] = v
|
11
|
+
when :if_modified_since then request["If-Modified-Since"] = v
|
12
|
+
else
|
13
|
+
raise ArgumentError.new("unknown header symbol #{k}") if k.is_a? Symbol
|
14
|
+
request[k] = v
|
15
|
+
end
|
16
|
+
end
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class HeaderResolver
|
4
|
+
include Mechanize::Handler
|
5
|
+
def initialize(keep_alive, keep_alive_time, cookie_jar, user_agent, headers)
|
6
|
+
@keep_alive = keep_alive
|
7
|
+
@keep_alive_time = keep_alive_time
|
8
|
+
@cookie_jar = cookie_jar
|
9
|
+
@user_agent = user_agent
|
10
|
+
@headers = headers
|
11
|
+
end
|
12
|
+
|
13
|
+
def handle(ctx, params)
|
14
|
+
uri = params[:uri]
|
15
|
+
referer = params[:referer]
|
16
|
+
request = params[:request]
|
17
|
+
|
18
|
+
if @keep_alive
|
19
|
+
request['Connection'] = 'keep-alive'
|
20
|
+
request['Keep-Alive'] = @keep_alive_time.to_s
|
21
|
+
else
|
22
|
+
request['Connection'] = 'close'
|
23
|
+
end
|
24
|
+
request['Accept-Encoding'] = 'gzip,identity'
|
25
|
+
request['Accept-Language'] = 'en-us,en;q=0.5'
|
26
|
+
host = "#{uri.host}#{[80, 443].include?(uri.port.to_i) ? '' : ':' + uri.port.to_s}"
|
27
|
+
request['Host'] = host
|
28
|
+
request['Accept-Charset'] = 'ISO-8859-1,utf-8;q=0.7,*;q=0.7'
|
29
|
+
|
30
|
+
unless @cookie_jar.empty?(uri)
|
31
|
+
cookies = @cookie_jar.cookies(uri)
|
32
|
+
cookie = cookies.length > 0 ? cookies.join("; ") : nil
|
33
|
+
request.add_field('Cookie', cookie)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add Referer header to request
|
37
|
+
if referer && referer.uri
|
38
|
+
request['Referer'] = referer.uri.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add User-Agent header to request
|
42
|
+
request['User-Agent'] = @user_agent if @user_agent
|
43
|
+
|
44
|
+
@headers.each do |k,v|
|
45
|
+
request[k] = v
|
46
|
+
end if request
|
47
|
+
super
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class ParameterResolver
|
4
|
+
include Mechanize::Handler
|
5
|
+
|
6
|
+
def handle(ctx, params)
|
7
|
+
parameters = params[:params]
|
8
|
+
uri = params[:uri]
|
9
|
+
case params[:verb]
|
10
|
+
when :head, :get, :delete, :trace
|
11
|
+
if parameters.length > 0
|
12
|
+
uri.query ||= ''
|
13
|
+
uri.query << '&' if uri.query.length > 0
|
14
|
+
uri.query << Util.build_query_string(parameters)
|
15
|
+
end
|
16
|
+
params[:params] = []
|
17
|
+
end
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class PreConnectHook
|
4
|
+
include Mechanize::Handler
|
5
|
+
|
6
|
+
attr_accessor :hooks
|
7
|
+
def initialize
|
8
|
+
@hooks = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle(ctx, params)
|
12
|
+
@hooks.each { |hook| hook.call(params) }
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class PostConnectHook < PreConnectHook
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class RequestResolver
|
4
|
+
include Mechanize::Handler
|
5
|
+
|
6
|
+
def handle(ctx, params)
|
7
|
+
uri = params[:uri]
|
8
|
+
if %w{ http https }.include?(uri.scheme.downcase)
|
9
|
+
klass = Net::HTTP.const_get(params[:verb].to_s.capitalize)
|
10
|
+
params[:request] ||= klass.new(uri.request_uri)
|
11
|
+
end
|
12
|
+
|
13
|
+
if %w{ file }.include?(uri.scheme.downcase)
|
14
|
+
o = Struct.new(:uri).new(uri)
|
15
|
+
class << o
|
16
|
+
def add_field(*args); end
|
17
|
+
alias :[]= :add_field
|
18
|
+
def path
|
19
|
+
uri.path
|
20
|
+
end
|
21
|
+
def each_header; end
|
22
|
+
end
|
23
|
+
params[:request] ||= o
|
24
|
+
end
|
25
|
+
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class ResponseBodyParser
|
4
|
+
include Mechanize::Handler
|
5
|
+
|
6
|
+
def initialize(pluggable_parser, watch_for_set)
|
7
|
+
@pluggable_parser = pluggable_parser
|
8
|
+
@watch_for_set = watch_for_set
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle(ctx, params)
|
12
|
+
response = params[:response]
|
13
|
+
response_body = params[:response_body]
|
14
|
+
uri = params[:uri]
|
15
|
+
|
16
|
+
content_type = nil
|
17
|
+
unless response['Content-Type'].nil?
|
18
|
+
data = response['Content-Type'].match(/^([^;]*)/)
|
19
|
+
content_type = data[1].downcase.split(',')[0] unless data.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Find our pluggable parser
|
23
|
+
params[:page] = @pluggable_parser.parser(content_type).new(
|
24
|
+
uri,
|
25
|
+
response,
|
26
|
+
response_body,
|
27
|
+
response.code
|
28
|
+
) { |parser|
|
29
|
+
parser.mech = params[:agent] if parser.respond_to? :mech=
|
30
|
+
if parser.respond_to?(:watch_for_set=) && @watch_for_set
|
31
|
+
parser.watch_for_set = @watch_for_set
|
32
|
+
end
|
33
|
+
}
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class Mechanize
|
2
|
+
class Chain
|
3
|
+
class ResponseHeaderHandler
|
4
|
+
include Mechanize::Handler
|
5
|
+
|
6
|
+
def initialize(cookie_jar, connection_cache)
|
7
|
+
@cookie_jar = cookie_jar
|
8
|
+
@connection_cache = connection_cache
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle(ctx, params)
|
12
|
+
response = params[:response]
|
13
|
+
uri = params[:uri]
|
14
|
+
page = params[:page]
|
15
|
+
cache_obj = (@connection_cache["#{uri.host}:#{uri.port}"] ||= {
|
16
|
+
:connection => nil,
|
17
|
+
:keep_alive_options => {},
|
18
|
+
})
|
19
|
+
|
20
|
+
# If the server sends back keep alive options, save them
|
21
|
+
if keep_alive_info = response['keep-alive']
|
22
|
+
keep_alive_info.split(/,\s*/).each do |option|
|
23
|
+
k, v = option.split(/\=/)
|
24
|
+
cache_obj[:keep_alive_options] ||= {}
|
25
|
+
cache_obj[:keep_alive_options][k.intern] = v
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
if page.is_a?(Page) && page.body =~ /Set-Cookie/n
|
30
|
+
page.search('//meta[@http-equiv="Set-Cookie"]').each do |meta|
|
31
|
+
Cookie::parse(uri, meta['content']) { |c|
|
32
|
+
Mechanize.log.debug("saved cookie: #{c}") if Mechanize.log
|
33
|
+
@cookie_jar.add(uri, c)
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
(response.get_fields('Set-Cookie')||[]).each do |cookie|
|
39
|
+
Cookie::parse(uri, cookie) { |c|
|
40
|
+
Mechanize.log.debug("saved cookie: #{c}") if Mechanize.log
|
41
|
+
@cookie_jar.add(uri, c)
|
42
|
+
}
|
43
|
+
end
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|