lib/oembed/provider.rb in ruby-oembed-0.7.6 vs lib/oembed/provider.rb in ruby-oembed-0.8.1
- old
+ new
@@ -1,68 +1,145 @@
module OEmbed
+ # An OEmbed::Provider has information about an individual oEmbed enpoint.
class Provider
- attr_accessor :format, :name, :url, :urls, :endpoint
+
+ # The String that is the http URI of the Provider's oEmbed endpoint.
+ # This URL may also contain a {{format}} portion. In actual requests to
+ # this Provider, this string will be replaced with a string representing
+ # the request format (e.g. "json").
+ attr_accessor :endpoint
+
+ # The name of the default format for all request to this Provider (e.g. 'json').
+ attr_accessor :format
+
+ # An Array of all URL schemes supported by this Provider.
+ attr_accessor :urls
+
+ # The human-readable name of the Provider.
+ #
+ # @deprecated *Note*: This accessor currently isn't used anywhere in the codebase.
+ attr_accessor :name
+
+ # @deprecated *Note*: Added in a fork of the gem, a while back. I really would like
+ # to get rid of it, though. --Marcos
+ attr_accessor :url
+
- def initialize(endpoint, format = OEmbed::Formatters::DEFAULT)
+ # Construct a new OEmbed::Provider instance, pointing at a specific oEmbed
+ # endpoint.
+ #
+ # The endpoint should be a String representing the http URI of the Provider's
+ # oEmbed endpoint. The endpoint String may also contain a {format} portion.
+ # In actual requests to this Provider, this string will be replaced with a String
+ # representing the request format (e.g. "json").
+ #
+ # If give, the format should be the name of the default format for all request
+ # to this Provider (e.g. 'json'). Defaults to OEmbed::Formatter.default
+ #
+ # For example:
+ # # If requests should be sent to:
+ # # "http://my.service.com/oembed?format=#{OEmbed::Formatter.default}"
+ # @provider = OEmbed::Provider.new("http://my.service.com/oembed")
+ #
+ # # If requests should be sent to:
+ # # "http://my.service.com/oembed.xml"
+ # @xml_provider = OEmbed::Provider.new("http://my.service.com/oembed.{format}", :xml)
+ def initialize(endpoint, format = OEmbed::Formatter.default)
+ endpoint_uri = URI.parse(endpoint.gsub(/[\{\}]/,'')) rescue nil
+ raise ArgumentError, "The given endpoint isn't a valid http(s) URI: #{endpoint.to_s}" unless endpoint_uri.is_a?(URI::HTTP)
+
@endpoint = endpoint
@urls = []
- # Try to use the best available format
- @format = OEmbed::Formatters.verify?(format)
+ @format = format
end
+ # Adds the given url scheme to this Provider instance.
+ # The url scheme can be either a String, containing wildcards specified
+ # with an asterisk, (see http://oembed.com/#section2.1 for details),
+ # or a Regexp.
+ #
+ # For example:
+ # @provider << "http://my.service.com/video/*"
+ # @provider << "http://*.service.com/photo/*/slideshow"
+ # @provider << %r{^http://my.service.com/((help)|(faq))/\d+[#\?].*}
def <<(url)
- if url.is_a? Regexp
- @urls << url
- return
+ if !url.is_a?(Regexp)
+ full, scheme, domain, path = *url.match(%r{([^:]*)://?([^/?]*)(.*)})
+ domain = Regexp.escape(domain).gsub("\\*", "(.*?)").gsub("(.*?)\\.", "([^\\.]+\\.)?")
+ path = Regexp.escape(path).gsub("\\*", "(.*?)")
+ url = Regexp.new("^#{Regexp.escape(scheme)}://#{domain}#{path}")
end
- 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}")
+ @urls << url
end
- def build(url, options = {})
+ # Send a request to the Provider endpoint to get information about the
+ # given url and return the appropriate OEmbed::Response.
+ #
+ # The query parameter should be a Hash of values which will be
+ # sent as query parameters in this request to the Provider endpoint. The
+ # following special cases apply to the query Hash:
+ # :format:: overrides this Provider's default request format.
+ # :url:: will be ignored, replaced by the url param.
+ def get(url, query = {})
+ query[:format] ||= @format
+ OEmbed::Response.create_for(raw(url, query), self, url, query[:format].to_s)
+ end
+
+ # Determine whether the given url is supported by this Provider by matching
+ # against the Provider's URL schemes.
+ def include?(url)
+ @urls.empty? || !!@urls.detect{ |u| u =~ url }
+ end
+
+ # @deprecated *Note*: This method will be made private in the future.
+ def build(url, query = {})
raise OEmbed::NotFound, url unless include?(url)
- query = options.merge({:url => url})
+
+ query = query.merge({:url=>url})
+ # TODO: move this code exclusively into the get method, once build is private.
+ this_format = (query[:format] ||= @format.to_s).to_s
+
endpoint = @endpoint.clone
- if format_in_url?
- format = endpoint["{format}"] = (query[:format] || @format).to_s
+ if endpoint.include?("{format}")
+ endpoint["{format}"] = this_format
query.delete(:format)
- else
- format = query[:format] ||= @format
end
- query_string = "?" + query.inject("") do |memo, (key, value)|
+ query = "?" + 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
+ URI.parse(endpoint + query).instance_eval do
+ @format = this_format
+ def format
+ @format
+ end
self
end
end
- def raw(url, options = {})
- uri = build(url, options)
+ # @deprecated *Note*: This method will be made private in the future.
+ def raw(url, query = {})
+ uri = build(url, query)
found = false
max_redirects = 4
until found
host, port = uri.host, uri.port if uri.host && uri.port
- res = Net::HTTP.start(uri.host, uri.port) {|http| http.get(uri.request_uri) }
+ res = Net::HTTP.start(uri.host, uri.port) {|http| http.get(uri.request_uri) }
res.header['location'] ? uri = URI.parse(res.header['location']) : found = true
if max_redirects == 0
found = true
else
max_redirects = max_redirects - 1
end
end
case res
when Net::HTTPNotImplemented
- raise OEmbed::UnknownFormat, uri.format
+ raise OEmbed::UnknownFormat, format
when Net::HTTPNotFound
raise OEmbed::NotFound, url
when Net::HTTPOK
res.body
else
@@ -72,26 +149,13 @@
# Convert known errors into OEmbed::UnknownResponse for easy catching
# up the line. This is important if given a URL that doesn't support
# OEmbed. The following are known errors:
# * Net::* errors like Net::HTTPBadResponse
# * JSON::JSONError errors like JSON::ParserError
- if $!.is_a?(JSON::JSONError) || $!.class.to_s =~ /\ANet::/
+ if defined?(::JSON) && $!.is_a?(::JSON::JSONError) || $!.class.to_s =~ /\ANet::/
raise OEmbed::UnknownResponse, res && res.respond_to?(:code) ? res.code : 'Error'
else
raise $!
end
- end
-
- def get(url, options = {})
- options[:format] ||= @format if @format
- OEmbed::Response.create_for(raw(url, options), self, url, options[:format])
- end
-
- def format_in_url?
- @endpoint.include?("{format}")
- end
-
- def include?(url)
- @urls.empty? || !!@urls.detect{ |u| u =~ url }
end
end
end