diff --git a/lib/funky/connections/api.rb b/lib/funky/connections/api.rb index a27fcb3..3e0cef4 100644 --- a/lib/funky/connections/api.rb +++ b/lib/funky/connections/api.rb @@ -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_id}%7C#{app_secret}" + uri = URI "https://#{host}/v2.9/#{path_query}&limit=100" fetch_data_with_paging_token(uri) end @@ -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_id}%7C#{app_secret}" + 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" @@ -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_id}%7C#{app_secret}&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_id}%7C#{app_secret}" + 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 @@ -94,10 +93,6 @@ def self.app_secret Funky.configuration.app_secret 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}"} diff --git a/lib/funky/connections/base.rb b/lib/funky/connections/base.rb index 2dd38db..86efcc7 100644 --- a/lib/funky/connections/base.rb +++ b/lib/funky/connections/base.rb @@ -5,11 +5,20 @@ 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) + uri = uri_with_query(uri, access_token: app_access_token) + http_request = 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 end @@ -17,6 +26,9 @@ def self.response_for(http_request, uri, max_retries = 5) response elsif response.is_a? Net::HTTPServerError sleep_and_retry_response_for(http_request, uri, max_retries, response.body) + elsif response.is_a?(Net::HTTPBadRequest) && response.body =~ /access token/i + @app_access_token = nil + response_for(http_request, uri) else raise ContentNotFound, "Error #{response.code}: #{response.body}" end @@ -37,6 +49,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.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}.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 diff --git a/spec/pages/find_spec.rb b/spec/pages/find_spec.rb index ce3ad59..837ae05 100644 --- a/spec/pages/find_spec.rb +++ b/spec/pages/find_spec.rb @@ -36,5 +36,17 @@ it { expect { page }.to raise_error(Funky::ContentNotFound) } end + + context 'with invalid app access token' do + before { Funky::Connection::API.instance_variable_set :@app_access_token, 'invalid-token' } + + context 'given an existing page ID' do + let(:page_id) { existing_page_id } + + specify 'does not raise error by refreshing' do + expect{ page }.not_to raise_error + end + end + end end end