urifetch 0.0.5 → 0.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -10,6 +10,8 @@ gem 'addressable'
10
10
  gem 'hashie'
11
11
  gem 'nokogiri'
12
12
  gem 'imagesize'
13
+ gem 'activesupport'
14
+ gem 'actionpack'
13
15
 
14
16
  group :development do
15
17
  gem "rspec"
data/Gemfile.lock CHANGED
@@ -1,25 +1,52 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ actionpack (3.2.0)
5
+ activemodel (= 3.2.0)
6
+ activesupport (= 3.2.0)
7
+ builder (~> 3.0.0)
8
+ erubis (~> 2.7.0)
9
+ journey (~> 1.0.0)
10
+ rack (~> 1.4.0)
11
+ rack-cache (~> 1.1)
12
+ rack-test (~> 0.6.1)
13
+ sprockets (~> 2.1.2)
14
+ activemodel (3.2.0)
15
+ activesupport (= 3.2.0)
16
+ builder (~> 3.0.0)
17
+ activesupport (3.2.0)
18
+ i18n (~> 0.6)
19
+ multi_json (~> 1.0)
4
20
  addressable (2.2.6)
21
+ builder (3.0.0)
5
22
  coderay (0.9.8)
6
23
  diff-lcs (1.1.3)
24
+ erubis (2.7.0)
7
25
  git (1.2.5)
8
26
  hashie (1.2.0)
27
+ hike (1.2.1)
28
+ i18n (0.6.0)
9
29
  imagesize (0.1.1)
10
30
  jeweler (1.6.4)
11
31
  bundler (~> 1.0)
12
32
  git (>= 1.2.5)
13
33
  rake
34
+ journey (1.0.1)
14
35
  json (1.6.4)
15
36
  method_source (0.6.7)
16
37
  ruby_parser (>= 2.3.1)
38
+ multi_json (1.0.4)
17
39
  nokogiri (1.5.0)
18
40
  pry (0.9.7.4)
19
41
  coderay (~> 0.9.8)
20
42
  method_source (~> 0.6.7)
21
43
  ruby_parser (>= 2.3.1)
22
44
  slop (~> 2.1.0)
45
+ rack (1.4.1)
46
+ rack-cache (1.1)
47
+ rack (>= 0.4)
48
+ rack-test (0.6.1)
49
+ rack (>= 1.0)
23
50
  rake (0.9.2.2)
24
51
  rcov (0.9.11)
25
52
  rdoc (3.12)
@@ -36,11 +63,18 @@ GEM
36
63
  sexp_processor (~> 3.0)
37
64
  sexp_processor (3.0.9)
38
65
  slop (2.1.0)
66
+ sprockets (2.1.2)
67
+ hike (~> 1.2)
68
+ rack (~> 1.0)
69
+ tilt (~> 1.1, != 1.3.0)
70
+ tilt (1.3.3)
39
71
 
40
72
  PLATFORMS
41
73
  ruby
42
74
 
43
75
  DEPENDENCIES
76
+ actionpack
77
+ activesupport
44
78
  addressable
45
79
  bundler (= 1.1.rc)
46
80
  hashie
@@ -0,0 +1,70 @@
1
+ module OpenGraph
2
+ # Fetch Open Graph data from the specified URI. Makes an
3
+ # HTTP GET request and returns an OpenGraph::Object if there
4
+ # is data to be found or <tt>false</tt> if there isn't.
5
+ #
6
+ # Pass <tt>false</tt> for the second argument if you want to
7
+ # see invalid (i.e. missing a required attribute) data.
8
+
9
+ def self.parse(doc, strict = true)
10
+ page = OpenGraph::Object.new
11
+ doc.css('meta').each do |m|
12
+ if m.attribute('property') && m.attribute('property').to_s.match(/^og:(.+)$/i)
13
+ page[$1.gsub('-','_')] = m.attribute('content').to_s
14
+ end
15
+ end
16
+ return false if page.keys.empty?
17
+ return false unless page.valid? if strict
18
+ page
19
+ end
20
+
21
+ TYPES = {
22
+ 'activity' => %w(activity sport),
23
+ 'business' => %w(bar company cafe hotel restaurant),
24
+ 'group' => %w(cause sports_league sports_team),
25
+ 'organization' => %w(band government non_profit school university),
26
+ 'person' => %w(actor athlete author director musician politician public_figure),
27
+ 'place' => %w(city country landmark state_province),
28
+ 'product' => %w(album book drink food game movie product song tv_show),
29
+ 'website' => %w(blog website)
30
+ }
31
+
32
+ # The OpenGraph::Object is a Hash with method accessors for
33
+ # all detected Open Graph attributes.
34
+ class Object < Hashie::Mash
35
+ MANDATORY_ATTRIBUTES = %w(title type image url)
36
+
37
+ # The object type.
38
+ def type
39
+ self['type']
40
+ end
41
+
42
+ # The schema under which this particular object lies. May be any of
43
+ # the keys of the TYPES constant.
44
+ def schema
45
+ OpenGraph::TYPES.each_pair do |schema, types|
46
+ return schema if types.include?(self.type)
47
+ end
48
+ nil
49
+ end
50
+
51
+ OpenGraph::TYPES.values.flatten.each do |type|
52
+ define_method "#{type}?" do
53
+ self.type == type
54
+ end
55
+ end
56
+
57
+ OpenGraph::TYPES.keys.each do |scheme|
58
+ define_method "#{scheme}?" do
59
+ self.type == scheme || OpenGraph::TYPES[scheme].include?(self.type)
60
+ end
61
+ end
62
+
63
+ # If the Open Graph information for this object doesn't contain
64
+ # the mandatory attributes, this will be <tt>false</tt>.
65
+ def valid?
66
+ MANDATORY_ATTRIBUTES.each{|a| return false unless self[a]}
67
+ true
68
+ end
69
+ end
70
+ end
@@ -2,12 +2,20 @@ module Urifetch
2
2
 
3
3
  class Response
4
4
 
5
- attr_reader :status, :strategy, :data
5
+ attr_accessor :status, :strategy_key, :data
6
6
 
7
- def initialize(args={})
8
- @status = args[:status] || ['0','']
9
- @strategy = args[:strategy] || Strategy.new(:test,"".match(//))
10
- @data = args[:data] || Hashie::Mash.new
7
+ def initialize(status,strategy_key,data)
8
+ @status = status
9
+ @strategy_key = strategy_key
10
+ @data = data
11
+ end
12
+
13
+ def to_h
14
+ @data
15
+ end
16
+
17
+ def to_json
18
+ to_h.to_json
11
19
  end
12
20
 
13
21
  end
@@ -0,0 +1,57 @@
1
+ module Urifetch
2
+
3
+ class Router
4
+
5
+ attr_reader :routes
6
+
7
+ def initialize(options={},&block)
8
+
9
+ options = default_options = {
10
+ strategy_key: "base",
11
+ class_name: "Urifetch::Strategy::Base"
12
+ }.merge(options)
13
+
14
+ @routes = Hash.new(options)
15
+
16
+ instance_eval(&block) if block_given?
17
+
18
+ @routes[/(?<base>(?<match_id>.*))/i] = @routes[""]
19
+ end
20
+
21
+ def find(uri)
22
+
23
+ # Tries to find a match
24
+ match_data = @routes.keys.map{|r|r.match(uri.to_s)}.reject{|r|r.nil?}[0]
25
+
26
+ # Fetches route data for given regex
27
+ route_data = @routes[match_data.regexp]
28
+
29
+ begin
30
+ # Spawns strategy instance by constantizing strategy name
31
+ class_name = route_data[:strategy_class] || "Urifetch::Strategy::" + route_data[:strategy_key].classify
32
+ strategy = class_name.constantize.new(uri,match_data,route_data)
33
+
34
+ rescue NameError
35
+ # Spawns base strategy instance
36
+ strategy = Strategy::Base.new(uri,match_data,route_data)
37
+ end
38
+
39
+ return strategy
40
+
41
+ end
42
+
43
+ private
44
+
45
+ def match(string,strategy_key,args={})
46
+
47
+ # Raises an ArgumentError if a non supported filetype is supplied.
48
+ raise ArgumentError "matcher ('#{string.class}') needs to be either 'String' or 'Regexp'" unless [String,Regexp].include?(string.class)
49
+ raise ArgumentError "strategy_key ('#{strategy_key.class}') needs to be either 'String' or 'Symbol'" unless [String,Symbol].include?(strategy_key.class)
50
+ # Stores the arguments in memory
51
+ routes[string] = { strategy_key: strategy_key.to_s }.merge(args)
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,101 @@
1
+ module Urifetch
2
+
3
+ module Strategy
4
+
5
+ class Base
6
+
7
+ attr_reader :uri, :match_data, :route_data, :response
8
+
9
+ def initialize(uri,match_data,route_data={})
10
+ @uri = uri
11
+ @match_data = match_data
12
+ @route_data = route_data
13
+ @response = Response.new(['0',''],route_data[:strategy_key],{})
14
+ end
15
+
16
+ def execute!
17
+ perform_request
18
+ process_request if response.status == ["200","OK"]
19
+ response
20
+ end
21
+
22
+ def perform_request
23
+ begin
24
+ timeout(30) { @request = open(@uri.to_s,'rb') }
25
+ set_status @request.status
26
+ rescue OpenURI::HTTPError => error
27
+ set_status error.message.split(" ",2)
28
+ rescue SocketError => error
29
+ set_status ["400","Bad Request"]
30
+ rescue Errno::ENOENT => error
31
+ set_status ["404","File not Found"]
32
+ rescue Errno::ECONNREFUSED => error
33
+ set_status ["401","Unauthorized"]
34
+ rescue Errno::EADDRINUSE
35
+ set_status ["401","Unauthorized"]
36
+ rescue RuntimeError => error
37
+ set_status ["400","Bad Request"]
38
+ rescue Exception => e
39
+ set_status ["500","Server Error",e]
40
+ rescue TimeOutError
41
+ set_status ["408","Request Timeout"]
42
+ else
43
+ set_status ["200","OK"]
44
+ end
45
+ end
46
+
47
+ def process_request
48
+
49
+ # Start by setting the URI
50
+ set :url, uri.to_s
51
+
52
+ doc = Nokogiri::HTML.parse(@request)
53
+
54
+ # Open Auth data
55
+ if og = OpenGraph.parse(doc)
56
+ set :url, og.url, override: true
57
+ set :title, og.title
58
+ set :image, og.image
59
+ set :description, og.description
60
+ end
61
+
62
+ # Custom CSS data
63
+ unless set? :title
64
+ t = doc.css('title').first
65
+ set :title, t.nil? ? match_data[0] : t.content.strip
66
+ end
67
+
68
+ favicon = doc.css('link[rel="shortcut icon"], link[rel="icon shortcut"], link[rel="shortcut"], link[rel="icon"]').first
69
+ favicon = favicon.nil? ? nil : favicon['href'].strip
70
+ if favicon
71
+ if favicon.match(/^https?:\/\//i).nil?
72
+ favicon = uri.scheme + "://" + uri.host.sub(/\/$/,"") + "/" + favicon.sub(/^\//,"")
73
+ end
74
+ set :favicon, favicon
75
+ end
76
+
77
+ end
78
+
79
+ private
80
+
81
+ def set_status(status_array)
82
+ response.status = status_array
83
+ end
84
+
85
+ def get(key)
86
+ response.data[key.to_s]
87
+ end
88
+
89
+ def set(key,value,args={})
90
+ response.data[key.to_s] = value if (args[:override] == true) or response.data[key.to_s].nil? unless value.nil?
91
+ end
92
+
93
+ def set?(key)
94
+ !response.data[key.to_s].nil?
95
+ end
96
+
97
+ end
98
+
99
+ end
100
+
101
+ end
@@ -0,0 +1,57 @@
1
+ class Urifetch::Strategy::Image < Urifetch::Strategy::Base
2
+
3
+ def process_request
4
+
5
+ # Works for ["PCX", "PSD", "XPM", "TIFF", "XBM", "PGM", "PBM", "PPM", "BMP", "JPEG", "PNG", "GIF", "SWF"]
6
+
7
+ # Preview File Source
8
+ set :image, @request.base_uri.to_s
9
+ set :url, @request.base_uri.to_s
10
+
11
+ # Title
12
+ set :title, File.basename(@request.base_uri.to_s)
13
+
14
+ # File Type
15
+ set :mime_type, @request.meta['content-type']
16
+
17
+ # File Size
18
+ set :image_size, number_to_human_size(@request.size)
19
+
20
+ unless get(:mime_type).match(/text\/html/i).nil?
21
+ doc = Nokogiri::HTML.parse(@request)
22
+
23
+ # Open Auth data
24
+ if og = OpenGraph.parse(doc)
25
+ set :url, og.url, override: true
26
+ set :title, og.title, override: true
27
+ set :image, og.image, override: true
28
+ end
29
+
30
+ unless set? :title
31
+ t = doc.css('title').first
32
+ set :title, t.nil? ? match_data[0] : t.content.strip
33
+ end
34
+
35
+ else
36
+
37
+ # Image Size
38
+ sizes = [nil,nil]
39
+ 3.times do |i|
40
+ begin
41
+ sizes = ImageSize.new(@request).get_size
42
+ rescue NoMethodError => e
43
+ sizes = ImageSize.new(@request.read).get_size
44
+ end
45
+ break if sizes != [nil,nil]
46
+ end
47
+
48
+ unless sizes == [nil,nil]
49
+ set :image_height, sizes[1]
50
+ set :image_width, sizes[0]
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -1,92 +1,9 @@
1
1
  module Urifetch
2
2
 
3
- require 'open-uri'
4
- require 'nokogiri'
5
- require 'image_size'
6
- require 'stringio'
7
-
8
- class Strategy
9
-
10
- autoload :Layout, 'urifetch/strategy/layout'
11
-
12
- @@layouts = Hashie::Mash.new
13
- def self.layouts
14
- @@layouts
15
- end
16
-
17
- attr_reader :layout, :match_data, :layout_key, :uri, :filehead, :skip_request
18
-
19
- def initialize(layout_key,match_data,args={})
20
- @skip_request = args[:skip_request] || false
21
- @layout_key = layout_key
22
- @match_data = match_data
23
- @layout = @@layouts[layout_key]
24
- raise "no matching layouts found on #{layout_key}" unless @layout
25
- end
26
-
27
- def self.layout(layout_key,&block)
28
- layouts[layout_key] = Layout.new(layout_key,&block)
29
- end
30
-
31
- def self.apply(layout_key,args={})
32
- m_data = args[:with] || "".match(//)
33
- Strategy.new(layout_key,m_data)
34
- end
35
-
36
- def self.apply!(layout_key,args={})
37
- apply(layout_key,args).execute!
38
- end
39
-
40
- def execute!
41
- run_before!
42
- if skip_request
43
- begin
44
- @uri = Addressable::URI.heuristic_parse(match_data.string)
45
- request = open(@uri.to_s,'rb')
46
- status = request.status
47
- run_on_success!(request)
48
- rescue OpenURI::HTTPError => error
49
- status = (error.message.split(" ",2))
50
- run_on_failure!(error)
51
- rescue SocketError => error
52
- status = (["400","Bad Request"])
53
- run_on_failure!(error)
54
- rescue Errno::ENOENT => error
55
- status = (["404","File not Found"])
56
- run_on_failure!(error)
57
- rescue Errno::ECONNREFUSED => error
58
- status = (["401","Unauthorized"])
59
- run_on_failure!(error)
60
- rescue RuntimeError => error
61
- status = (["400","Bad Request"])
62
- run_on_failure!(error)
63
- rescue Exception => e
64
- status = (["500","Server Error",e])
65
- end
66
- else
67
- status = (["200","OK"])
68
- end
69
- return Response.new(status: status, strategy: self, data: @data)
70
- end
71
-
72
- private
73
-
74
- def run_before!
75
- instance_exec(&layout.before) unless layout.before.nil?
76
- end
77
-
78
- def run_on_success!(request)
79
- @uri = request.base_uri
80
- instance_exec(request,&layout.success) unless layout.before.nil?
81
- end
82
-
83
- def run_on_failure!(error)
84
- instance_exec(error,&layout.failure) unless layout.before.nil?
85
- end
3
+ module Strategy
86
4
 
87
- def data
88
- @data ||= Hashie::Mash.new
89
- end
5
+ autoload :Base, 'urifetch/strategy/base'
6
+ autoload :Image, 'urifetch/strategy/image'
90
7
 
91
8
  end
92
9
 
@@ -3,9 +3,9 @@ module Urifetch
3
3
  module Version
4
4
 
5
5
  MAJOR = 0
6
- MINOR = 0
7
- PATCH = 5
8
- BUILD = nil
6
+ MINOR = 1
7
+ PATCH = 0
8
+ BUILD = 'rc1'
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
11
11
 
data/lib/urifetch.rb CHANGED
@@ -1,139 +1,51 @@
1
- require 'hashie/mash'
1
+ require 'hashie'
2
+ require 'open-uri'
3
+ require 'nokogiri'
4
+ require 'image_size'
5
+ require 'stringio'
2
6
  require 'addressable/uri'
3
- #require 'pry'
7
+ require 'active_support/inflector'
8
+ require 'timeout'
9
+
10
+ require 'action_view'
11
+ include ActionView::Helpers::NumberHelper
12
+
13
+ # require 'pry'
4
14
 
5
15
  module Urifetch
6
16
 
7
- DEFAULT_MATCH_STRING = /(.*)/i
8
- DEFAULT_STRATEGY = :default
9
-
10
- autoload :Handler, 'urifetch/handler'
11
- autoload :Strategy, 'urifetch/strategy'
12
17
  autoload :Response, 'urifetch/response'
18
+ autoload :Strategy, 'urifetch/strategy'
19
+ autoload :Router, 'urifetch/router'
20
+ autoload :Version, 'urifetch/version'
21
+
22
+ autoload :OpenGraph, 'urifetch/ext/opengraph'
13
23
 
14
- @@handler = Handler.new(DEFAULT_STRATEGY)
15
-
16
- def self.fetch_from(url,args={})
17
- find_strategy_from(url).execute!
18
- end
24
+ @@router = Router.new()
19
25
 
20
- def self.find_strategy_from(url,args={})
26
+ def self.fetch(url,args={})
21
27
  if valid_url?(url)
22
- @@handler.find(url)
28
+ uri = Addressable::URI.heuristic_parse(url.to_s)
29
+ @@router.find(uri).execute!
23
30
  else
24
- raise ArgumentError, "invalid url"
31
+ raise ArgumentError, "Invalid URL"
25
32
  end
26
33
  end
27
34
 
28
35
  def self.valid_url?(url)
36
+ # Validates URL according to Cloudsdale.org standards
29
37
  !(url =~ /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix).nil?
30
38
  end
31
39
 
32
- def self.register(&block)
33
- @@handler.instance_eval(&block)
34
- end
35
-
36
- end
37
-
38
- Urifetch.register do
39
- match /\.(PCX|PSD|XPM|TIFF|XBM|PGM|PBM|PPM|BMP|JPEG|JPG||PNG|GIF|SWF)$/i, :image
40
- end
41
-
42
- Urifetch::Strategy.layout(:test) do
43
-
44
- before_request do
45
- end
46
-
47
- after_success do |request|
48
- end
49
-
50
- after_failure do |error|
40
+ def self.route(args={},&block)
41
+ @@router = Router.new(args) do
42
+ instance_eval(&block)
43
+ end
51
44
  end
52
45
 
53
46
  end
54
47
 
55
- Urifetch::Strategy.layout(:default) do
56
-
57
- before_request do
58
- end
59
-
60
- after_success do |request|
61
- doc = Nokogiri::HTML(request)
62
-
63
- # Title
64
- title = doc.css('title').first
65
- data.title = title.nil? ? match_data[0] : title.content.strip
66
-
67
- # Favicon
68
- favicon = doc.css('link[rel="shortcut icon"], link[rel="icon shortcut"], link[rel="shortcut"], link[rel="icon"]').first
69
- favicon = favicon.nil? ? nil : favicon['href'].strip
70
- if favicon
71
- if favicon.match(/^https?:\/\//i).nil?
72
- favicon = uri.scheme + "://" + uri.host + favicon
73
- end
74
- data.favicon = favicon
75
- end
76
- end
77
-
78
- after_failure do |error|
79
- end
80
-
48
+ Urifetch.route do
49
+ match /(?<image>(?<match_id>\.(?<file_type>PCX|PSD|XPM|TIFF|XBM|PGM|PBM|PPM|BMP|JPEG|JPG||PNG|GIF|SWF))$)/i, :image, strategy_class: 'Urifetch::Strategy::Image'
81
50
  end
82
51
 
83
- Urifetch::Strategy.layout(:image) do
84
-
85
- before_request do
86
- end
87
-
88
- after_success do |request|
89
- # Works for ["PCX", "PSD", "XPM", "TIFF", "XBM", "PGM", "PBM", "PPM", "BMP", "JPEG", "PNG", "GIF", "SWF"]
90
-
91
- # Match ID
92
- data.match_id = request.base_uri.to_s
93
-
94
- # Title
95
- data.title = File.basename(request.base_uri.to_s)
96
-
97
- # File Type
98
- data.mime_type = request.meta['content-type']
99
-
100
- # Preview File Source
101
- data.preview_image = request.base_uri.to_s
102
-
103
- unless data.mime_type.match(/text\/html/i).nil?
104
- doc = Nokogiri::HTML(request)
105
- t = data.title.sub(/^.*\:/i,'')
106
- t2 = t.sub(/\./i,"\\.")
107
- src = doc.search('img').map(&:attributes).map{|h|h["src"].to_s}.reject{|u|u.match(/#{t2}/i).nil?}.first
108
- src.sub!(/^\/\//i,'http://')
109
- if src
110
- data.title = t
111
- @uri = Addressable::URI.heuristic_parse(src)
112
- data.match_id = @uri.to_s
113
- request = open(@uri.to_s,'rb')
114
- data.mime_type = request.meta['content-type']
115
- end
116
- end
117
-
118
- # Image Size
119
- data.image_size = [nil,nil]
120
- 3.times do |i|
121
- begin
122
- data.image_size = ImageSize.new(request).get_size
123
- rescue NoMethodError => e
124
- data.image_size = ImageSize.new(request.read).get_size# unless e.message.match(/undefined method `type' for/).nil?
125
- end
126
- break if data.image_size != [nil,nil]
127
- end
128
-
129
- end
130
-
131
- after_failure do |error|
132
- # File Type
133
- data.mime_type = 'unknown'
134
-
135
- # Image Size
136
- data.image_size = [0,0]
137
- end
138
-
139
- end
@@ -2,108 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  describe Urifetch do
4
4
 
5
- describe 'self.fetch_from' do
6
-
7
- it 'should return a Urifetch::Response' do
8
- Urifetch.fetch_from(Urifetch::Test::UrlHelpers.generate_valid_url).should be_a_kind_of(Urifetch::Response)
9
- end
10
-
11
- it 'should raise an error if url is invalid according to configuration' do
12
- -> { Urifetch.fetch_from(Urifetch::Test::UrlHelpers.generate_invalid_url) }.should raise_error ArgumentError, "invalid url"
13
- end
14
-
15
- end
16
-
17
- describe 'self.find_strategy_from' do
18
-
19
- it 'should an instance of Urifetch::Strategy' do
20
- Urifetch.find_strategy_from("http://www.google.com").should be_an_instance_of Urifetch::Strategy
21
- end
22
-
23
- end
24
-
25
- describe 'strategy' do
26
-
27
- describe 'default' do
28
-
29
- it 'should return title and favicon for valid path' do
30
- @response = Urifetch.fetch_from("http://www.youtube.com")
31
- @response.data.should have_key(:title)
32
- @response.data.should have_key(:favicon)
33
- end
34
-
35
- it 'should return title and NOT favicon for valid path' do
36
- @response = Urifetch.fetch_from("http://www.google.com")
37
- @response.data.should have_key(:title)
38
- @response.data.should_not have_key(:favicon)
39
- end
40
-
41
- end
42
-
43
- describe 'image' do
44
-
45
- it 'should return image properties and file name for valid png file' do
46
- @url = "http://www.google.com/intl/en_com/images/srpr/logo3w.png"
47
- @title = "logo3w.png"
48
- @match_id = "http://www.google.com/intl/en_com/images/srpr/logo3w.png"
49
- @mime_type = "image/png"
50
- @image_size = [275, 95]
51
- end
52
-
53
- it 'should return image properties and file name for valid jpg file' do
54
- @url = "http://i.imgur.com/ab9Gd.jpg"
55
- @title = "ab9Gd.jpg"
56
- @match_id = "http://i.imgur.com/ab9Gd.jpg"
57
- @mime_type = "image/jpeg"
58
- @image_size = [492, 362]
59
- end
60
-
61
- it 'should return image properties and file name for valid gif file' do
62
- @url = "http://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif"
63
- @title = "Rotating_earth_%28large%29.gif"
64
- @match_id = "http://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif"
65
- @mime_type = "image/gif"
66
- @image_size = [400, 400]
67
- end
68
-
69
- it 'should return image properties and file name for valid bmp file' do
70
- @url = "http://www.gonmad.co.uk/satnav/bmp_blank.bmp"
71
- @title = "bmp_blank.bmp"
72
- @match_id = "http://www.gonmad.co.uk/satnav/bmp_blank.bmp"
73
- @mime_type = "image/bmp"
74
- @image_size = [16, 16]
75
- end
76
-
77
- it 'should return image properties and file name for valid gif file even though the initial minetype is html' do
78
- @url = "http://en.wikipedia.org/wiki/File:Sunflower_as_gif_small.gif"
79
- @title = "Sunflower_as_gif_small.gif"
80
- @match_id = "http://upload.wikimedia.org/wikipedia/commons/e/e2/Sunflower_as_gif_small.gif"
81
- @mime_type = "image/gif"
82
- @image_size = [250, 297]
83
- end
84
-
85
- after(:each) do
86
- @response = Urifetch.fetch_from(@url)
87
-
88
- # Check Title
89
- @response.data.should have_key(:title)
90
- @response.data[:title].should == @title
91
-
92
- # Check Match ID
93
- @response.data.should have_key(:match_id)
94
- @response.data[:match_id].should == @match_id
95
-
96
- # Check FileType
97
- @response.data.should have_key(:mime_type)
98
- @response.data[:mime_type].should == @mime_type
99
-
100
- # Check ImageSize
101
- @response.data.should have_key(:image_size)
102
- @response.data[:image_size].should == @image_size
103
- end
104
-
105
- end
106
-
5
+ it 'should return a response' do
6
+ mlfw = Urifetch.fetch("http://mylittlefacewhen.com/f/2446/") #.should be_a(Urifetch::Response)
7
+ goog = Urifetch.fetch("http://www.google.com") #.should be_a(Urifetch::Response)
8
+ tube = Urifetch.fetch("http://www.youtube.com/watch?v=xPfMb50dsOk")
9
+ jpeg = Urifetch.fetch("http://www.dreamincode.net/forums/uploads/monthly_05_2010/post-380028-12747928967239.jpg.pagespeed.ce.yRppR_j7ae.jpg")
107
10
  end
108
11
 
109
12
  end
data/urifetch.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "urifetch"
8
- s.version = "0.0.5"
8
+ s.version = "0.1.0.rc1"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Philip Vieira"]
12
- s.date = "2012-01-24"
12
+ s.date = "2012-02-15"
13
13
  s.description = "Urifetch allows you to fetch data from any URL using pattern matching. The library allows for dynamically adding match handlers as well as build your own strategies."
14
14
  s.email = "philip@vallin.se"
15
15
  s.extra_rdoc_files = [
@@ -27,17 +27,15 @@ Gem::Specification.new do |s|
27
27
  "Rakefile",
28
28
  "lib/.DS_Store",
29
29
  "lib/urifetch.rb",
30
- "lib/urifetch/handler.rb",
30
+ "lib/urifetch/ext/opengraph.rb",
31
31
  "lib/urifetch/response.rb",
32
+ "lib/urifetch/router.rb",
32
33
  "lib/urifetch/strategy.rb",
33
- "lib/urifetch/strategy/layout.rb",
34
+ "lib/urifetch/strategy/base.rb",
35
+ "lib/urifetch/strategy/image.rb",
34
36
  "lib/urifetch/version.rb",
35
37
  "spec/helpers/url_helpers.rb",
36
38
  "spec/spec_helper.rb",
37
- "spec/urifetch/handler_spec.rb",
38
- "spec/urifetch/response_spec.rb",
39
- "spec/urifetch/strategy/layout_spec.rb",
40
- "spec/urifetch/strategy_spec.rb",
41
39
  "spec/urifetch_spec.rb",
42
40
  "urifetch.gemspec"
43
41
  ]
@@ -55,6 +53,8 @@ Gem::Specification.new do |s|
55
53
  s.add_runtime_dependency(%q<hashie>, [">= 0"])
56
54
  s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
57
55
  s.add_runtime_dependency(%q<imagesize>, [">= 0"])
56
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
57
+ s.add_runtime_dependency(%q<actionpack>, [">= 0"])
58
58
  s.add_development_dependency(%q<rspec>, [">= 0"])
59
59
  s.add_development_dependency(%q<bundler>, ["= 1.1.rc"])
60
60
  s.add_development_dependency(%q<jeweler>, [">= 0"])
@@ -66,6 +66,8 @@ Gem::Specification.new do |s|
66
66
  s.add_dependency(%q<hashie>, [">= 0"])
67
67
  s.add_dependency(%q<nokogiri>, [">= 0"])
68
68
  s.add_dependency(%q<imagesize>, [">= 0"])
69
+ s.add_dependency(%q<activesupport>, [">= 0"])
70
+ s.add_dependency(%q<actionpack>, [">= 0"])
69
71
  s.add_dependency(%q<rspec>, [">= 0"])
70
72
  s.add_dependency(%q<bundler>, ["= 1.1.rc"])
71
73
  s.add_dependency(%q<jeweler>, [">= 0"])
@@ -78,6 +80,8 @@ Gem::Specification.new do |s|
78
80
  s.add_dependency(%q<hashie>, [">= 0"])
79
81
  s.add_dependency(%q<nokogiri>, [">= 0"])
80
82
  s.add_dependency(%q<imagesize>, [">= 0"])
83
+ s.add_dependency(%q<activesupport>, [">= 0"])
84
+ s.add_dependency(%q<actionpack>, [">= 0"])
81
85
  s.add_dependency(%q<rspec>, [">= 0"])
82
86
  s.add_dependency(%q<bundler>, ["= 1.1.rc"])
83
87
  s.add_dependency(%q<jeweler>, [">= 0"])
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: urifetch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
5
- prerelease:
4
+ version: 0.1.0.rc1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Philip Vieira
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-24 00:00:00.000000000Z
12
+ date: 2012-02-15 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: addressable
16
- requirement: &70237495253880 !ruby/object:Gem::Requirement
16
+ requirement: &70202067777280 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70237495253880
24
+ version_requirements: *70202067777280
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: hashie
27
- requirement: &70237495253280 !ruby/object:Gem::Requirement
27
+ requirement: &70202067776560 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70237495253280
35
+ version_requirements: *70202067776560
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: nokogiri
38
- requirement: &70237495252700 !ruby/object:Gem::Requirement
38
+ requirement: &70202067775820 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70237495252700
46
+ version_requirements: *70202067775820
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: imagesize
49
- requirement: &70237495252100 !ruby/object:Gem::Requirement
49
+ requirement: &70202067775080 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,32 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70237495252100
57
+ version_requirements: *70202067775080
58
+ - !ruby/object:Gem::Dependency
59
+ name: activesupport
60
+ requirement: &70202067774280 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70202067774280
69
+ - !ruby/object:Gem::Dependency
70
+ name: actionpack
71
+ requirement: &70202067773580 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *70202067773580
58
80
  - !ruby/object:Gem::Dependency
59
81
  name: rspec
60
- requirement: &70237495251520 !ruby/object:Gem::Requirement
82
+ requirement: &70202067772780 !ruby/object:Gem::Requirement
61
83
  none: false
62
84
  requirements:
63
85
  - - ! '>='
@@ -65,10 +87,10 @@ dependencies:
65
87
  version: '0'
66
88
  type: :development
67
89
  prerelease: false
68
- version_requirements: *70237495251520
90
+ version_requirements: *70202067772780
69
91
  - !ruby/object:Gem::Dependency
70
92
  name: bundler
71
- requirement: &70237495250860 !ruby/object:Gem::Requirement
93
+ requirement: &70202067772000 !ruby/object:Gem::Requirement
72
94
  none: false
73
95
  requirements:
74
96
  - - =
@@ -76,10 +98,10 @@ dependencies:
76
98
  version: 1.1.rc
77
99
  type: :development
78
100
  prerelease: false
79
- version_requirements: *70237495250860
101
+ version_requirements: *70202067772000
80
102
  - !ruby/object:Gem::Dependency
81
103
  name: jeweler
82
- requirement: &70237495250260 !ruby/object:Gem::Requirement
104
+ requirement: &70202067771360 !ruby/object:Gem::Requirement
83
105
  none: false
84
106
  requirements:
85
107
  - - ! '>='
@@ -87,10 +109,10 @@ dependencies:
87
109
  version: '0'
88
110
  type: :development
89
111
  prerelease: false
90
- version_requirements: *70237495250260
112
+ version_requirements: *70202067771360
91
113
  - !ruby/object:Gem::Dependency
92
114
  name: rcov
93
- requirement: &70237495249620 !ruby/object:Gem::Requirement
115
+ requirement: &70202067752040 !ruby/object:Gem::Requirement
94
116
  none: false
95
117
  requirements:
96
118
  - - ! '>='
@@ -98,10 +120,10 @@ dependencies:
98
120
  version: '0'
99
121
  type: :development
100
122
  prerelease: false
101
- version_requirements: *70237495249620
123
+ version_requirements: *70202067752040
102
124
  - !ruby/object:Gem::Dependency
103
125
  name: pry
104
- requirement: &70237495248960 !ruby/object:Gem::Requirement
126
+ requirement: &70202067751460 !ruby/object:Gem::Requirement
105
127
  none: false
106
128
  requirements:
107
129
  - - ! '>='
@@ -109,10 +131,10 @@ dependencies:
109
131
  version: '0'
110
132
  type: :development
111
133
  prerelease: false
112
- version_requirements: *70237495248960
134
+ version_requirements: *70202067751460
113
135
  - !ruby/object:Gem::Dependency
114
136
  name: rdoc
115
- requirement: &70237495248320 !ruby/object:Gem::Requirement
137
+ requirement: &70202067750840 !ruby/object:Gem::Requirement
116
138
  none: false
117
139
  requirements:
118
140
  - - ! '>='
@@ -120,7 +142,7 @@ dependencies:
120
142
  version: '0'
121
143
  type: :development
122
144
  prerelease: false
123
- version_requirements: *70237495248320
145
+ version_requirements: *70202067750840
124
146
  description: Urifetch allows you to fetch data from any URL using pattern matching.
125
147
  The library allows for dynamically adding match handlers as well as build your own
126
148
  strategies.
@@ -141,17 +163,15 @@ files:
141
163
  - Rakefile
142
164
  - lib/.DS_Store
143
165
  - lib/urifetch.rb
144
- - lib/urifetch/handler.rb
166
+ - lib/urifetch/ext/opengraph.rb
145
167
  - lib/urifetch/response.rb
168
+ - lib/urifetch/router.rb
146
169
  - lib/urifetch/strategy.rb
147
- - lib/urifetch/strategy/layout.rb
170
+ - lib/urifetch/strategy/base.rb
171
+ - lib/urifetch/strategy/image.rb
148
172
  - lib/urifetch/version.rb
149
173
  - spec/helpers/url_helpers.rb
150
174
  - spec/spec_helper.rb
151
- - spec/urifetch/handler_spec.rb
152
- - spec/urifetch/response_spec.rb
153
- - spec/urifetch/strategy/layout_spec.rb
154
- - spec/urifetch/strategy_spec.rb
155
175
  - spec/urifetch_spec.rb
156
176
  - urifetch.gemspec
157
177
  homepage: http://github.com/zeeraw/Urifetch
@@ -169,13 +189,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
169
189
  version: '0'
170
190
  segments:
171
191
  - 0
172
- hash: 4158633268281007023
192
+ hash: -4352591540806531180
173
193
  required_rubygems_version: !ruby/object:Gem::Requirement
174
194
  none: false
175
195
  requirements:
176
- - - ! '>='
196
+ - - ! '>'
177
197
  - !ruby/object:Gem::Version
178
- version: '0'
198
+ version: 1.3.1
179
199
  requirements: []
180
200
  rubyforge_project:
181
201
  rubygems_version: 1.8.10
@@ -1,31 +0,0 @@
1
- module Urifetch
2
-
3
-
4
- class Handler
5
-
6
- def initialize(strategy_key,&block)
7
- @handlers = {}
8
- raise ArgumentError "strategy ('#{strategy.class}') needs to be a 'Symbol'" unless strategy_key.kind_of?(Symbol)
9
- @strategy_key = strategy_key || DEFAULT_STRATEGY
10
- instance_eval(&block) if block_given?
11
- end
12
-
13
- def find(url,previous_match=nil)
14
- previous_match = url.match(DEFAULT_MATCH_STRING) if previous_match.nil?
15
- @handlers.each do |key,val|
16
- m = url.match(key)
17
- return val.find(url,m) if m != 0 and !m.nil?
18
- end
19
- return Urifetch::Strategy.apply(@strategy_key, with: previous_match)
20
- end
21
-
22
- private
23
-
24
- def match(string,strategy,&block)
25
- raise ArgumentError "matcher ('#{key.class}') needs to be either 'String' or 'Regexp'" unless [String,Regexp].include?(string.class)
26
- @handlers[string] = Handler.new(strategy,&block)
27
- end
28
-
29
- end
30
-
31
- end
@@ -1,35 +0,0 @@
1
- module Urifetch
2
-
3
- class Strategy
4
-
5
- class Layout
6
-
7
- attr_reader :before, :success, :failure
8
-
9
- def initialize(args={},&block)
10
- @success = nil
11
- @failure = nil
12
- @before = nil
13
- instance_exec(args,&block) if block_given?
14
- end
15
-
16
- def after_success(&block)
17
- raise ArgumentError unless block_given?
18
- @success = block
19
- end
20
-
21
- def after_failure(&block)
22
- raise ArgumentError unless block_given?
23
- @failure = block
24
- end
25
-
26
- def before_request(&block)
27
- raise ArgumentError unless block_given?
28
- @before = block
29
- end
30
-
31
- end
32
-
33
- end
34
-
35
- end
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Urifetch::Handler do
4
-
5
- describe '#initialize' do
6
-
7
- it 'should return Urifetch::Handler' do
8
- Urifetch::Handler.new(:default).should be_a_kind_of Urifetch::Handler
9
- end
10
-
11
- it 'should have a default value of a Hash on @handlers' do
12
- @handlers = Urifetch::Handler.new(:default).instance_variable_get(:@handlers)
13
- @handlers.should_not be_nil
14
- @handlers.should be_a_kind_of Hash
15
- end
16
-
17
- end
18
-
19
- end
@@ -1,28 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Urifetch::Response do
4
-
5
- describe '#initialize' do
6
-
7
- before do
8
- @response = Urifetch::Response.new()
9
- end
10
-
11
- it 'should contain status as an array' do
12
- @response.status.should_not be_nil
13
- @response.status.should be_a_kind_of(Array)
14
- end
15
-
16
- it 'should contain the strategy used when matching' do
17
- @response.strategy.should_not be_nil
18
- @response.strategy.should be_a_kind_of(Urifetch::Strategy)
19
- end
20
-
21
- it 'should contain data as a hashie/mash' do
22
- @response.data.should_not be_nil
23
- @response.data.should be_a_kind_of(Hashie::Mash)
24
- end
25
-
26
- end
27
-
28
- end
@@ -1,51 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Urifetch::Strategy::Layout do
4
-
5
- before do
6
- @layout = Urifetch::Strategy::Layout.new do
7
-
8
- after_success do
9
- some_method
10
- end
11
-
12
- after_failure do
13
- some_method
14
- end
15
-
16
- before_request do
17
- some_method
18
- end
19
-
20
- end
21
- end
22
-
23
- describe 'after_success' do
24
-
25
- it 'should overwrite the value proc' do
26
- proc = @layout.instance_variable_get(:@success)
27
- @layout.after_success do
28
- some_method
29
- end
30
- proc.should_not eq(@layout.instance_variable_get(:@success))
31
- end
32
-
33
- it 'should overwrite the value proc' do
34
- proc = @layout.instance_variable_get(:@failure)
35
- @layout.after_failure do
36
- some_method
37
- end
38
- proc.should_not eq(@layout.instance_variable_get(:@failure))
39
- end
40
-
41
- it 'should overwrite the value proc' do
42
- proc = @layout.instance_variable_get(:@before)
43
- @layout.before_request do
44
- some_method
45
- end
46
- proc.should_not eq(@layout.instance_variable_get(:@before))
47
- end
48
-
49
- end
50
-
51
- end
@@ -1,67 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Urifetch::Strategy do
4
-
5
- describe 'self.layouts' do
6
-
7
- it 'should return an Hashie::Mash' do
8
- Urifetch::Strategy.layouts.should be_a_kind_of Hashie::Mash
9
- end
10
-
11
- end
12
-
13
- describe 'self.layout' do
14
-
15
- it 'should return a Urifetch::Strategy::Layout instance and make it accessible through .layouts' do
16
- @layout = Urifetch::Strategy.layout(:test) do; end
17
- @layout.should be_an_instance_of Urifetch::Strategy::Layout
18
- Urifetch::Strategy.layouts[:test].should == @layout
19
- end
20
-
21
- end
22
-
23
- describe 'self.apply' do
24
-
25
- it 'should return an instance of Urifetch::Strategy' do
26
- Urifetch::Strategy.apply(:test).should be_an_instance_of Urifetch::Strategy
27
- end
28
-
29
- end
30
-
31
- describe 'self.apply!' do
32
-
33
- it 'should return an instance of Urifetch::Response' do
34
- Urifetch::Strategy.apply!(:test).should be_an_instance_of Urifetch::Response
35
- end
36
-
37
- end
38
-
39
- before do
40
- @strategy = Urifetch::Strategy.new(:test,"".match(//i))
41
- end
42
-
43
- describe '#initialize' do
44
-
45
- it 'should return an error if layout was not found' do
46
- -> { Urifetch::Strategy.new(:not_found,"".match(//i)) }.should raise_error(RuntimeError, /no matching layouts found/i)
47
- end
48
-
49
- it 'should contain match data as a MatchData object' do
50
- @strategy.match_data.should be_a_kind_of MatchData
51
- end
52
-
53
- it 'should have a layout as a Urifetch::Strategy::Layout' do
54
- @strategy.layout.should be_an_instance_of Urifetch::Strategy::Layout
55
- end
56
-
57
- end
58
-
59
- describe 'execute!' do
60
-
61
- it 'should return an instance of Urifetch::Response' do
62
- @strategy.execute!.should be_an_instance_of Urifetch::Response
63
- end
64
-
65
- end
66
-
67
- end