Class: Embedly::API

Inherits:
Object
  • Object
show all
Defined in:
lib/embedly/api.rb

Overview

Performs api calls to embedly.

You won’t find methods. We are using method_missing and passing the method name to apicall.

Currently Supported Methods

  • oembed

  • objectify

  • preview

All methods return ostructs, so fields can be accessed with the dot operator. ex.

api = Embedly::API.new
obj = api.oembed :url => 'http://blog.doki-pen.org/'
puts obj[0].title, obj[0].description, obj[0].thumbnail_url

Call parameters should be passed as the opts parameter. If set, key will automatically be added to the query string of the call, so no need to set it.

This API would be future compatible, if not for the version. In order to add support for a new method, you will need to add a version to the api_version hash. Here is an example.

api = Embedly::API.new
api.api_version[:new_method] = 3
api.new_method :arg1 => '1', :arg2 => '2'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ API

Options

:hostname

Hostname of embedly server. Defaults to api.embed.ly.

:key

Your api.embed.ly key.

:secret

Your api.embed.ly secret if you are using oauth.

:user_agent

Your User-Agent header. Defaults to Mozilla/5.0 (compatible; embedly-ruby/VERSION;)

:timeout

Request timeout (in seconds). Defaults to 180 seconds or 3 minutes

:headers

Additional headers to send with requests.



51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/embedly/api.rb', line 51

def initialize opts={}
  @endpoints = [:oembed, :objectify, :preview]
  @key = opts[:key]
  @secret = opts[:secret] == "" ? nil : opts[:secret]
  @api_version = Hash.new('1')
  @api_version.merge!({:objectify => '2'})
  @hostname = opts[:hostname] || 'api.embed.ly'
  @timeout = opts[:timeout] || 180
  @headers = {
    'User-Agent' => opts[:user_agent] || "Mozilla/5.0 (compatible; embedly-ruby/#{Embedly::VERSION};)"
  }.merge(opts[:headers]||{})
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

Performs api call based on method name

Currently supported

  • oembed

  • objectify

  • preview



198
199
200
201
202
203
204
205
206
207
# File 'lib/embedly/api.rb', line 198

def method_missing(name, *args, &block)
  if @endpoints.include?name
    opts = args[0]
    opts[:action] = name
    opts[:version] = @api_version[name]
    apicall opts
  else
    super
  end
end

Instance Attribute Details

#api_versionObject (readonly)

Returns the value of attribute api_version.



41
42
43
# File 'lib/embedly/api.rb', line 41

def api_version
  @api_version
end

#headersObject (readonly)

Returns the value of attribute headers.



41
42
43
# File 'lib/embedly/api.rb', line 41

def headers
  @headers
end

#hostnameObject (readonly)

Returns the value of attribute hostname.



41
42
43
# File 'lib/embedly/api.rb', line 41

def hostname
  @hostname
end

#keyObject (readonly)

Returns the value of attribute key.



41
42
43
# File 'lib/embedly/api.rb', line 41

def key
  @key
end

#secretObject (readonly)

Returns the value of attribute secret.



41
42
43
# File 'lib/embedly/api.rb', line 41

def secret
  @secret
end

Instance Method Details

#_do_basic_call(path) ⇒ Object



71
72
73
74
75
76
77
78
# File 'lib/embedly/api.rb', line 71

def _do_basic_call path
  scheme, host, port = uri_parse hostname
  logger.debug { "calling #{site}#{path} with headers #{headers} using Net::HTTP" }
  Net::HTTP.start(host, port, :use_ssl => scheme == 'https') do |http|
    http.read_timeout = @timeout
    http.get(path, headers)
  end
end

#_do_call(path) ⇒ Object



93
94
95
96
97
98
99
# File 'lib/embedly/api.rb', line 93

def _do_call path
  if key and secret
    _do_oauth_call path
  else
    configuration.typhoeus ? _do_typhoeus_call(path) : _do_basic_call(path)
  end
end

#_do_oauth_call(path) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/embedly/api.rb', line 80

def _do_oauth_call path
  consumer = OAuth::Consumer.new(key, secret,
    :site => site,
    :http_method => :get,
    :scheme => :query_string)
  # our implementation is broken for header authorization, thus the
  # query_string

  access_token = OAuth::AccessToken.new consumer
  logger.debug { "calling #{site}#{path} with headers #{headers} via OAuth" }
  access_token.get path, headers
end

#_do_typhoeus_call(path) ⇒ Object



64
65
66
67
68
69
# File 'lib/embedly/api.rb', line 64

def _do_typhoeus_call path
  scheme, host, port = uri_parse hostname
  url = "#{scheme}://#{hostname}:#{port}#{path}"
  logger.debug { "calling #{site}#{path} with headers #{headers} using Typhoeus" }
  Typhoeus::Request.get(url, {:headers => headers, :timeout => (@timeout*1000) })
end

#apicall(opts) ⇒ Object

Use methods oembed, objectify, preview in favor of this method.

Normalizes url and urls parameters and calls the endpoint. url OR urls must be present

Options

:url

_(optional)_ A single url

:urls

_(optional)_ An array of urls

:action

The method that should be called. ex. oembed, objectify, preview

:version

The api version number.

others

All other parameters are used as query strings.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/embedly/api.rb', line 113

def apicall opts
  opts[:urls] ||= []
  opts[:urls] << opts[:url] if opts[:url]

  raise 'must pass urls' if opts[:urls].size == 0

  params = {:urls => opts[:urls]}

  # store unsupported services as errors and don't send them to embedly
  rejects = []
  if not key
    params[:urls].reject!.with_index do |url, i|
      if url !~ services_regex
        rejects << [i,
          Embedly::EmbedlyObject.new(
            :type => 'error',
            :error_code => 401,
            :error_message => 'Embedly api key is required.'
          )
        ]
      end
    end
  end

  if params[:urls].size > 0
    params[:key] = key if key and not secret
    params.merge!Hash[
      opts.select{|k,_| not [:url, :urls, :action, :version].index k}
    ]

    path = "/#{opts[:version]}/#{opts[:action]}?#{QueryString.stringify(params)}"

    response = _do_call path

    if response.code.to_i == 200
      logger.debug { response.body }
      # [].flatten is to be sure we have an array
      objs = [JSON.parse(response.body)].flatten.collect do |o|
        Embedly::EmbedlyObject.new(o)
      end
    else
      logger.debug { response }
      raise Embedly::BadResponseException.new(response, path)
    end

    # re-insert rejects into response
    rejects.each do |i, obj|
      objs.insert i, obj
    end

    objs
  else
    # we only have rejects, return them without calling embedly
    rejects.collect{|i, obj| obj}
  end
end

#servicesObject

Returns structured data from the services API method.

Response is cached per API object.

see api.embed.ly/docs/service for a description of the response.



175
176
177
178
179
180
181
182
# File 'lib/embedly/api.rb', line 175

def services
  if not @services
    response = _do_call '/1/services/ruby'
    raise 'services call failed', response if response.code.to_i != 200
    @services = JSON.parse(response.body)
  end
  @services
end

#services_regexObject

Returns a regex suitable for checking urls against for non-key usage



185
186
187
188
# File 'lib/embedly/api.rb', line 185

def services_regex
  r = services.collect {|p| p["regex"].join("|")}.join("|")
  Regexp.new r
end