module OEmbed
class RisingCodeCache
@cache_enabled = false
class << self
attr_writer :expiry, :host
def enabled?
@cache_enabled
end
def enable!
@cache ||= MemCache.new(host, :namespace => "openuri")
@cache_enabled = true
end
def disable!
@cache_enabled = false
end
def disabled?
!@cache_enabled
end
def get(key)
@cache.get(key)
end
def set(key, value)
@cache.set(key, value, expiry)
end
def expiry
@expiry ||= 60 * 60 * 24
end
def alive?
servers = @cache.instance_variable_get(:@servers) and servers.collect{|s| s.alive?}.include?(true)
end
def host
@host ||= "localhost:11211"
end
end
end
class Provider
attr_accessor :format, :name, :url, :urls, :endpoint
def initialize(endpoint, format = :json)
@endpoint = endpoint
@urls = []
@format = format
end
def <<(url)
full, scheme, domain, path = *url.match(%r{([^:]*)://?([^/?]*)(.*)})
domain = Regexp.escape(domain).gsub("\\*", "(.*?)").gsub("(.*?)\\.", "([^\\.]+\\.)?")
path = Regexp.escape(path).gsub("\\*", "(.*?)")
@urls << Regexp.new("^#{Regexp.escape(scheme)}://#{domain}#{path}")
end
def build(url, options = {})
raise OEmbed::NotFound, url unless include?(url)
query = options.merge({:url => url})
endpoint = @endpoint.clone
if format_in_url?
format = endpoint["{format}"] = (query[:format] || @format).to_s
query.delete(:format)
else
format = query[:format] ||= @format
end
query_string = "?" + query.inject("") do |memo, (key, value)|
"#{key}=#{value}&#{memo}"
end.chop
URI.parse(endpoint + query_string).instance_eval do
@format = format; def format; @format; end
self
end
end
def raw(url, options = {})
uri = build(url, options)
if RisingCodeCache.enabled? and RisingCodeCache::alive?
begin
response = RisingCodeCache::get(url)
rescue
response = nil
end
end
unless response
res = Net::HTTP.start(uri.host, uri.port) do |http|
http.get(uri.request_uri)
end
case res
when Net::HTTPNotImplemented
response = Exception.new
when Net::HTTPNotFound
response = Exception.new
when Net::HTTPOK
response = res.body
else
response = Exception.new
end
RisingCodeCache::set(url, response) if RisingCodeCache.alive?
end
raise response if response.is_a? Exception
StringIO.new(response)
end
def get(url, options = {})
OEmbed::Response.create_for(raw(url, options.merge(:format => :json)), self)
end
def format_in_url?
@endpoint.include?("{format}")
end
def include?(url)
@urls.empty? || !!@urls.detect{ |u| u =~ url }
end
end
end