Permalink
Browse files

Updated the logic to follow redirects. For example, when getting the …

…favicon for http://linkedin.com, we need to first follow the redirect to http://www.linkedin.com, then parse that page for the favicon link.
  • Loading branch information...
1 parent 8e8f926 commit caf875f0650fd0a46ce09ab86839baaa17facffa @myronmarston myronmarston committed Nov 13, 2009
Showing with 57 additions and 34 deletions.
  1. +22 −17 lib/www/favicon.rb
  2. +35 −17 spec/www-favicon_spec.rb
View
39 lib/www/favicon.rb
@@ -8,8 +8,8 @@ class Favicon
VERSION = '0.0.5'
def find(url)
- html = request(url).body
- find_from_html(html, url)
+ response = request(url)
+ find_from_html(response.body, response.request_url)
end
def find_from_html(html, url)
@@ -20,20 +20,14 @@ def find_from_html(html, url)
favicon_url
end
- def valid_favicon_url?(url, limit = 10)
- return false if limit == 0
-
+ def valid_favicon_url?(url)
response = request(url)
- if response.kind_of?(Net::HTTPRedirection)
- valid_favicon_url?(response['Location'], limit - 1)
- else
- (
- response.code =~ /\A2/ &&
- response.body.to_s != '' &&
- response.content_type =~ /image/i
- ) ? true : false
- end
+ (
+ response.code =~ /\A2/ &&
+ response.body.to_s != '' &&
+ response.content_type =~ /image/i
+ ) ? true : false
end
private
@@ -66,7 +60,10 @@ def default_path(url)
uri.to_s
end
- def request(url, method = 'get')
+ def request(url, options = {})
+ method = options[:method] || :get
+ redirection_limit = options[:redirection_limit] || 10
+
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
@@ -75,12 +72,20 @@ def request(url, method = 'get')
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
- http.start do |http|
+ response = http.start do |http|
path =
(uri.path.empty? ? '/' : uri.path) +
(uri.query ? '?' + uri.query : '') +
(uri.fragment ? '#' + uri.fragment : '')
- response = http.send(method, path)
+ http.send(method, path)
+ end
+
+ if response.kind_of?(Net::HTTPRedirection) && redirection_limit > 0
+ request(response['Location'], :redirection_limit => redirection_limit - 1)
+ else
+ response.instance_variable_set('@request_url', url)
+ def response.request_url; @request_url; end
+ response
end
end
end
View
52 spec/www-favicon_spec.rb
@@ -3,6 +3,7 @@
$LOAD_PATH << File.dirname(__FILE__) + '/../lib/'
require 'www/favicon'
+require 'fakeweb'
describe WWW::Favicon do
before do
@@ -23,33 +24,38 @@
it "should find from url" do
@htmls.each do |html|
- @favicon.should_receive(:request).and_return expectaction(:body => html)
+ @favicon.should_receive(:request).and_return expectaction(:body => html, :request_url => 'http://example.com')
@favicon.find('http://example.com/').should == 'http://example.com/foo/favicon.ico'
end
end
-
+
it "should find from html and url" do
@htmls.each do |html|
@favicon.find_from_html(html, 'http://example.com/').should == 'http://example.com/foo/favicon.ico'
end
end
+
+ it "should use the request_url of the returned response to construct the favicon url for relative paths" do
+ @favicon.should_receive(:request).and_return expectaction(:body => '<html><link rel="Shortcut Icon" href="/foo/favicon.ico" /></html>', :request_url => 'http://images.example.com')
+ @favicon.find('http://example.com/').should == 'http://images.example.com/foo/favicon.ico'
+ end
it "should find from default path" do
- @favicon.should_receive(:request).and_return(expectaction(:body => '<html></html>'))
+ @favicon.should_receive(:request).and_return(expectaction(:body => '<html></html>', :request_url => 'http://www.example.com'))
@favicon.find('http://www.example.com/').should == 'http://www.example.com/favicon.ico'
@favicon.should_not_receive(:request)
@favicon.find_from_html('<html></html>', 'http://www.example.com/').should == 'http://www.example.com/favicon.ico'
end
it "should validate url" do
- @favicon.stub!(:request).and_return(expectaction(:body => '<html></html>'))
+ @favicon.stub!(:request).and_return(expectaction(:body => '<html></html>', :request_url => 'http://www.example.com'))
@favicon.should_receive(:valid_favicon_url?)
@favicon.find('http://www.example.com/')
end
it "should return nil if #valid_favicon_url? returns false" do
- @favicon.should_receive(:request).and_return(expectaction(:body => '<html></html>'))
+ @favicon.should_receive(:request).and_return(expectaction(:body => '<html></html>', :request_url => 'http://www.example.com'))
@favicon.should_receive(:valid_favicon_url?).and_return(false)
@favicon.find('http://www.example.com/').should be_nil
end
@@ -80,25 +86,37 @@
@response.content_type = 'application/xml'
@favicon.valid_favicon_url?(@url).should == false
end
+ end
- it 'should follow redirect' do
- @favicon.stub!(:request).and_return(@response)
- @response.should_receive(:kind_of?).and_return(true)
- @response.should_receive(:'[]').with('Location').and_return('http://example.com/foo/favicon.ico')
- @response.should_receive(:kind_of?).and_return(false)
+ describe '#request' do
+ after(:each) do
+ FakeWeb.clean_registry
+ end
- @favicon.valid_favicon_url?(@url).should == true
+ it 'should return the response from the given url' do
+ FakeWeb.register_uri(:get, "http://example.com", :body => 'The response body')
+ @response = @favicon.send(:request, 'http://example.com')
+ @response.body.should == 'The response body'
+ @response.request_url.should == 'http://example.com'
end
- it 'should return false if redirect limit is exceeded' do
- @favicon.stub!(:request).and_return(@response)
+ it 'should follow redirects' do
+ FakeWeb.register_uri(:get, "http://example.com", :status => ['301', 'Moved Permanently'], :location => 'http://www.example.com')
+ FakeWeb.register_uri(:get, "http://www.example.com", :body => 'The response body')
+ @response = @favicon.send(:request, 'http://example.com')
+ @response.body.should == 'The response body'
+ @response.request_url.should == 'http://www.example.com'
+ end
- 10.times do |i|
- @response.should_receive(:kind_of?).and_return(true)
- @response.should_receive(:'[]').with('Location').and_return("http://example.com/#{i}/favicon.ico")
+ it 'should only follow up to 10 redirects' do
+ 1.upto(12) do |i|
+ FakeWeb.register_uri(:get, "http://example.com/path#{i-1}", :status => ['301', 'Moved Permanently'], :location => "http://example.com/path#{i}")
end
- @favicon.valid_favicon_url?(@url).should == false
+ FakeWeb.register_uri(:get, "http://example.com/path11", :body => 'The response body')
+ @response = @favicon.send(:request, 'http://example.com/path0')
+ @response.should be_kind_of(Net::HTTPRedirection)
+ @response.request_url.should == 'http://example.com/path10'
end
end
end

0 comments on commit caf875f

Please sign in to comment.