require "net/http" require "cgi" require "uri" require "rubygems" require "json" require "longurl/constants" require "longurl/exceptions" require "longurl/url" module LongURL class Service def initialize(params = {}) if params[:cache].nil? @@cache = Hash.new elsif params[:cache] == false @@cache = nil else @@cache = params[:cache] end @@supported_services = cached_or_fetch_supported_services end def query_supported_service_only(url) check url raise LongURL::UnsupportedService unless service_supported?(url) (@@cache && cached_query(url)) || query(url) end def cached_query(url) @@cache[url] ||= query(url) end def query(url) escaped_url = check_and_escape(url) Net::HTTP.start(EndPoint.host, EndPoint.port) do |http| handle_response http.get("#{EndPoint.path}?format=json&url=#{escaped_url}") end rescue Timeout::Error, Errno::ENETUNREACH, Errno::ETIMEDOUT, SocketError raise LongURL::NetworkError end # Check among supported services by longurl.org if given url is supported. # Returns true if supported, false otherwise. def service_supported?(url) @@supported_services.include? URI.parse(url).host.downcase end protected # Returns a list of supported services. # Use cache to get the list or fetch it if cache is empty. def cached_or_fetch_supported_services if @@cache @@cache['supported_services'] ||= fetch_supported_services else fetch_supported_services end end # Check given url using LongURL::URL.check def check(url) LongURL::URL.check url end # Check given url and escape it for http query argument passing. def check_and_escape(url) check url CGI.escape url end # Fetch supported services from longurl.org api. # Returns supported services in an Array. # Raises LongURL::NetworkError in case of a network error (timeout, ...) def fetch_supported_services Net::HTTP.start(ServiceEndPoint.host, ServiceEndPoint.port) do |http| response = http.get("#{ServiceEndPoint.path}?format=json") parsed = JSON.parse(response.body) parsed.values.flatten end rescue Timeout::Error, Errno::ENETUNREACH, Errno::ETIMEDOUT, SocketError raise LongURL::NetworkError rescue raise LongURL::UnknownError end def handle_response(response) parsed = JSON.parse(response.body) parsed = parsed.first if parsed.is_a?(Array) if parsed['long_url'] parsed['long_url'] elsif parsed['message'] # Error raise exception_regarding_message(parsed['message']) else raise LongURL::UnknownError end end def exception_class_regarding_message(message) case message when 'Unsupported service.' LongURL::UnsupportedService when 'Connection timeout' LongURL::NetworkError when 'Could not expand URL. Please check that you have submitted a valid URL.' LongURL::InvalidURL else LongURL::UnknownError end end end end