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