urifetch 0.0.5 → 0.1.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -0
- data/Gemfile.lock +34 -0
- data/lib/urifetch/ext/opengraph.rb +70 -0
- data/lib/urifetch/response.rb +13 -5
- data/lib/urifetch/router.rb +57 -0
- data/lib/urifetch/strategy/base.rb +101 -0
- data/lib/urifetch/strategy/image.rb +57 -0
- data/lib/urifetch/strategy.rb +3 -86
- data/lib/urifetch/version.rb +3 -3
- data/lib/urifetch.rb +29 -117
- data/spec/urifetch_spec.rb +5 -102
- data/urifetch.gemspec +13 -9
- metadata +52 -32
- data/lib/urifetch/handler.rb +0 -31
- data/lib/urifetch/strategy/layout.rb +0 -35
- data/spec/urifetch/handler_spec.rb +0 -19
- data/spec/urifetch/response_spec.rb +0 -28
- data/spec/urifetch/strategy/layout_spec.rb +0 -51
- data/spec/urifetch/strategy_spec.rb +0 -67
data/Gemfile
CHANGED
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
|
data/lib/urifetch/response.rb
CHANGED
@@ -2,12 +2,20 @@ module Urifetch
|
|
2
2
|
|
3
3
|
class Response
|
4
4
|
|
5
|
-
|
5
|
+
attr_accessor :status, :strategy_key, :data
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@status
|
9
|
-
@
|
10
|
-
@data
|
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
|
data/lib/urifetch/strategy.rb
CHANGED
@@ -1,92 +1,9 @@
|
|
1
1
|
module Urifetch
|
2
2
|
|
3
|
-
|
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
|
-
|
88
|
-
|
89
|
-
end
|
5
|
+
autoload :Base, 'urifetch/strategy/base'
|
6
|
+
autoload :Image, 'urifetch/strategy/image'
|
90
7
|
|
91
8
|
end
|
92
9
|
|
data/lib/urifetch/version.rb
CHANGED
data/lib/urifetch.rb
CHANGED
@@ -1,139 +1,51 @@
|
|
1
|
-
require 'hashie
|
1
|
+
require 'hashie'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'image_size'
|
5
|
+
require 'stringio'
|
2
6
|
require 'addressable/uri'
|
3
|
-
|
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
|
-
@@
|
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.
|
26
|
+
def self.fetch(url,args={})
|
21
27
|
if valid_url?(url)
|
22
|
-
|
28
|
+
uri = Addressable::URI.heuristic_parse(url.to_s)
|
29
|
+
@@router.find(uri).execute!
|
23
30
|
else
|
24
|
-
raise ArgumentError, "
|
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.
|
33
|
-
@@
|
34
|
-
|
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
|
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
|
data/spec/urifetch_spec.rb
CHANGED
@@ -2,108 +2,11 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Urifetch do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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.
|
8
|
+
s.version = "0.1.0.rc1"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
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-
|
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/
|
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/
|
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
|
-
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-
|
12
|
+
date: 2012-02-15 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: addressable
|
16
|
-
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: *
|
24
|
+
version_requirements: *70202067777280
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: hashie
|
27
|
-
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: *
|
35
|
+
version_requirements: *70202067776560
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: nokogiri
|
38
|
-
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: *
|
46
|
+
version_requirements: *70202067775820
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: imagesize
|
49
|
-
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: *
|
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: &
|
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: *
|
90
|
+
version_requirements: *70202067772780
|
69
91
|
- !ruby/object:Gem::Dependency
|
70
92
|
name: bundler
|
71
|
-
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: *
|
101
|
+
version_requirements: *70202067772000
|
80
102
|
- !ruby/object:Gem::Dependency
|
81
103
|
name: jeweler
|
82
|
-
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: *
|
112
|
+
version_requirements: *70202067771360
|
91
113
|
- !ruby/object:Gem::Dependency
|
92
114
|
name: rcov
|
93
|
-
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: *
|
123
|
+
version_requirements: *70202067752040
|
102
124
|
- !ruby/object:Gem::Dependency
|
103
125
|
name: pry
|
104
|
-
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: *
|
134
|
+
version_requirements: *70202067751460
|
113
135
|
- !ruby/object:Gem::Dependency
|
114
136
|
name: rdoc
|
115
|
-
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: *
|
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/
|
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/
|
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:
|
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:
|
198
|
+
version: 1.3.1
|
179
199
|
requirements: []
|
180
200
|
rubyforge_project:
|
181
201
|
rubygems_version: 1.8.10
|
data/lib/urifetch/handler.rb
DELETED
@@ -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
|