Skip to content

Commit

Permalink
refresh app_access_token when expired
Browse files Browse the repository at this point in the history
  • Loading branch information
kangkyu committed Oct 25, 2017
1 parent 78e6453 commit eb7b967
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 24 deletions.
23 changes: 5 additions & 18 deletions lib/funky/connections/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Funky
module Connection
class API < Base
def self.fetch_all(path_query)
uri = URI "https://#{host}/v2.9/#{path_query}&limit=100&access_token=#{app_access_token}"
uri = URI "https://#{host}/v2.9/#{path_query}&limit=100"
fetch_data_with_paging_token(uri)
end

Expand All @@ -24,7 +24,7 @@ def self.fetch_data_with_paging_token(uri)
end

def self.fetch(path_query, is_array: false)
uri = URI "https://#{host}/v2.8/#{path_query}&limit=100&access_token=#{app_access_token}"
uri = URI "https://#{host}/v2.8/#{path_query}&limit=100"
is_array ? fetch_multiple_pages(uri).uniq : json_for(uri)
rescue URI::InvalidURIError
raise Funky::ContentNotFound, "Invalid URL"
Expand Down Expand Up @@ -66,17 +66,16 @@ def self.fetch_multiple_pages(uri)
def self.request(id:, fields:)
uri = URI::HTTPS.build host: host,
path: "/v2.8/#{id}",
query: "access_token=#{app_access_token}&fields=#{fields}"
query: "fields=#{fields}"
response_for(get_http_request(uri), uri)
end

def self.batch_request(ids:, fields:)
uri = URI::HTTPS.build host: host,
path: "/",
query: "include_headers=false&access_token=#{app_access_token}"
query: "include_headers=false"
batch = create_batch_for ids, fields
http_request = post_http_request uri
http_request.set_form_data batch: batch.to_json
http_request = post_http_request(uri, batch: batch.to_json)
response_for(http_request, uri)
end

Expand All @@ -94,18 +93,6 @@ def self.app_secret
Funky.configuration.app_secret
end

def self.app_access_token
@app_access_token ||= begin
uri = URI::HTTPS.build host: host, path: "/v2.8/oauth/access_token",
query: URI.encode_www_form({client_id: app_id, client_secret: app_secret, grant_type: 'client_credentials'})
Funky::Connection::API.json_for(uri)[:access_token]
end
end

def self.post_http_request(uri)
Net::HTTP::Post.new uri
end

def self.create_batch_for(ids, fields)
ids.map do |id|
{"method":"GET", "relative_url": "/v2.8/#{id}?fields=#{fields}"}
Expand Down
55 changes: 49 additions & 6 deletions lib/funky/connections/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,39 @@ class Base

private

def self.post_http_request(uri, form_data={})
http_request = Net::HTTP::Post.new uri
http_request.set_form_data form_data
http_request
end

def self.get_http_request(uri)
Net::HTTP::Get.new(uri.request_uri)
Net::HTTP::Get.new(uri)
end

def self.response_for(http_request, uri, max_retries = 5)
def self.response_for(http_request, uri, max_retries = 2)
uri = uri_with_query(uri, access_token: app_access_token)
req = req_with_query(http_request, access_token: app_access_token)
response = Net::HTTP.start(uri.host, 443, use_ssl: true) do |http|
http.request http_request
http.request req
end
if response.is_a? Net::HTTPSuccess
response
elsif response.is_a? Net::HTTPServerError
sleep_and_retry_response_for(http_request, uri, max_retries, response.body)
sleep_and_retry_response_for(req, uri, max_retries, response.body)
elsif response.is_a?(Net::HTTPBadRequest) && response.body =~ /access token/i
@app_access_token = nil
response_for(req, uri)
else
raise ContentNotFound, "Error #{response.code}: #{response.body}"
end
rescue SocketError => e
sleep_and_retry_response_for(http_request, uri, max_retries, e.message)
sleep_and_retry_response_for(req, uri, max_retries, e.message)
end

def self.sleep_and_retry_response_for(http_request, uri, retries, message)
if retries > 0
sleep (6 - retries) ** 2
sleep (3 - retries) ** 2
response_for http_request, uri, retries - 1
else
raise ConnectionError, message
Expand All @@ -37,6 +48,38 @@ def self.json_for(uri, max_retries = 3)
response = response_for(get_http_request(uri), uri)
JSON.parse(response.body, symbolize_names: true)
end

def self.uri_with_query(uri, query={})
return nil if uri.nil?
new_query = URI.decode_www_form(uri.query).to_h.merge(query)
uri.query = URI.encode_www_form(new_query)
uri
end

def self.req_with_query(http_request, query={})
return nil if http_request.nil?
new_uri = uri_with_query(http_request.uri, query)
case http_request
when Net::HTTP::Get
get_http_request(new_uri)
when Net::HTTP::Post
req = Net::HTTP::Post.new new_uri
req.set_form_data URI.decode_www_form(http_request.body)
req
end
end

def self.app_access_token
@app_access_token ||= begin
uri = URI::HTTPS.build host: host, path: "/v2.8/oauth/access_token",
query: URI.encode_www_form({client_id: app_id, client_secret: app_secret, grant_type: 'client_credentials'})
req = get_http_request(uri)
response = Net::HTTP.start(uri.host, 443, use_ssl: true) do |http|
http.request req
end
JSON.parse(response.body, symbolize_names: true)[:access_token]
end
end
end
end
end

0 comments on commit eb7b967

Please sign in to comment.