new action built-in functions: callAPI
did
committed Dec 21, 2016
commit 5d06483c3484b8d79e5d567d983e26d4c566f82f
Showing 5
changed files with
93 additions
and 27 deletions
locomotive/steam/services.rb b/lib/locomotive/steam/services.rb
+1
-1
| @@ | @@ -63,7 +63,7 @@ module Locomotive |
| end | |
| register :action do | |
| - | Steam::ActionService.new(current_site, email, content_entry) |
| + | Steam::ActionService.new(current_site, email, content_entry, external_api) |
| end | |
| register :content_entry do | |
locomotive/steam/services/action_service.rb b/lib/locomotive/steam/services/action_service.rb
+7
-2
| @@ | @@ -20,9 +20,10 @@ module Locomotive |
| allEntries | |
| findEntry | |
| createEntry | |
| - | updateEntry) |
| + | updateEntry |
| + | callAPI) |
| - | attr_accessor_initialize :site, :email, :content_entry_service |
| + | attr_accessor_initialize :site, :email, :content_entry_service, :api_service |
| def run(script, params = {}, liquid_context) | |
| context = Duktape::Context.new | |
| @@ | @@ -86,6 +87,10 @@ module Locomotive |
| -> (type, id_or_slug, attributes) { content_entry_service.update(type, id_or_slug, attributes, true) } | |
| end | |
| + | def call_api_lambda(liquid_context) |
| + | -> (method, url, options) { api_service.consume(url, (options || {}).with_indifferent_access.merge(method: method)) } |
| + | end |
| + | |
| end | |
| end | |
locomotive/steam/services/external_api_service.rb b/lib/locomotive/steam/services/external_api_service.rb
+42
-23
| @@ | @@ -7,52 +7,71 @@ module Locomotive |
| include ::HTTParty | |
| + | # Available option keys: |
| + | # - method |
| + | # - data |
| + | # - format |
| + | # - username / password (basic auth) |
| + | # - headers |
| + | # - header_auth |
| + | # - with_user_agent |
| + | # |
| def consume(url, options = {}) | |
| - | options[:base_uri], path = extract_base_uri_and_path(url) |
| + | base_uri, path = extract_base_uri_and_path(url) |
| - | options.delete(:format) if options[:format] == 'default' |
| + | method = (options[:method] || 'GET').to_s.downcase |
| - | # auth ? |
| - | username, password = options.delete(:username), options.delete(:password) |
| - | options[:basic_auth] = { username: username, password: password } if username |
| + | _options = build_httpparty_options(options, method) |
| + | _options[:base_uri] = base_uri |
| - | # authorization header ? |
| - | header_auth = options.delete(:header_auth) |
| - | options[:headers] = { 'Authorization' => header_auth } if header_auth |
| - | |
| - | perform_request_to(path, options) |
| + | perform_request_to(method, path, _options) |
| end | |
| private | |
| + | def build_httpparty_options(options, method) |
| + | _options = {} |
| + | |
| + | # data: body (POST/PUT/PATCH) or query (GET) |
| + | _options[method == 'get' ? :query : :body] = options[:data] if options[:data] |
| + | |
| + | # basic auth? |
| + | username, password = options[:username], options[:password] |
| + | _options[:basic_auth] = { username: username, password: password } if username |
| + | |
| + | # headers |
| + | _options[:headers] = options[:headers] || {} |
| + | _options[:headers]['Authorization'] = options[:header_auth] if options[:header_auth] |
| + | _options[:headers]['User-Agent'] = 'LocomotiveCMS' if options[:with_user_agent] |
| + | _options.delete(:headers) if _options[:headers].blank? |
| + | |
| + | # format |
| + | if options.has_key?(:format) && options[:format] != 'default' |
| + | _options[:format] = options[:format].gsub(/[\'\"]/, '').to_sym |
| + | end |
| + | |
| + | _options |
| + | end |
| + | |
| def extract_base_uri_and_path(url) | |
| url = HTTParty.normalize_base_uri(url) | |
| uri = URI.parse(url) | |
| path = uri.request_uri || '/' | |
| base_uri = "#{uri.scheme}://#{uri.host}" | |
| - | base_uri += ":#{uri.port}" if uri.port != 80 |
| + | base_uri += ":#{uri.port}" if (uri.port != 80 && uri.port != 443) |
| [base_uri, path] | |
| end | |
| - | def perform_request_to(path, options) |
| - | # [DEBUG] puts "[WebService] consuming #{path}, #{options.inspect}" |
| - | |
| - | # sanitize the options |
| - | options[:format] = options[:format].gsub(/[\'\"]/, '').to_sym if options.has_key?(:format) |
| - | if options[:with_user_agent] |
| - | user_agent = { 'User-Agent' => 'LocomotiveCMS' } |
| - | options[:headers] ? options[:headers].merge!(user_agent) : options[:headers] = user_agent |
| - | end |
| - | |
| - | response = self.class.get(path, options) |
| + | def perform_request_to(method, path, options) |
| + | response = self.class.send(method.to_sym, path, options) |
| parsed_response = response.parsed_response | |
| if response.code == 200 | |
| HashConverter.to_underscore(parsed_response) | |
| else | |
| - | Locomotive::Common::Logger.error "[WebService] consumed #{path}, #{options.inspect}, response = #{response.inspect}" |
| + | Locomotive::Common::Logger.error "[WebService] consumed [#{method.to_s.upcase}] #{path}, #{options.inspect}, response = #{response.inspect}" |
| nil | |
| end | |
| end | |
spec/unit/services/action_service_spec.rb
+21
-1
| @@ | @@ -6,7 +6,8 @@ describe Locomotive::Steam::ActionService do |
| let(:site) { instance_double('Site', as_json: site_hash ) } | |
| let(:email_service) { instance_double('EmailService') } | |
| let(:entry_service) { instance_double('ContentService') } | |
| - | let(:service) { described_class.new(site, email_service, entry_service) } |
| + | let(:api_service) { instance_double('ExternalAPIService') } |
| + | let(:service) { described_class.new(site, email_service, entry_service, api_service) } |
| describe '#run' do | |
| @@ | @@ -166,6 +167,25 @@ describe Locomotive::Steam::ActionService do |
| end | |
| + | describe 'callAPI' do |
| + | |
| + | let(:script) { "callAPI('POST', 'https://api.stripe.com/v1/charges', { username: 'abcdefghij', data: { token: '123456789' } })" } |
| + | |
| + | it 'forwards the action to the external api service' do |
| + | expect(api_service).to receive(:consume).with( |
| + | 'https://api.stripe.com/v1/charges', { |
| + | method: 'POST', |
| + | username: 'abcdefghij', |
| + | data: { |
| + | token: '123456789' |
| + | } |
| + | } |
| + | ) |
| + | subject |
| + | end |
| + | |
| + | end |
| + | |
| end | |
| end | |
spec/unit/services/external_api_service_spec.rb
+22
-0
| @@ | @@ -85,6 +85,28 @@ describe Locomotive::Steam::ExternalAPIService do |
| end | |
| end | |
| + | describe 'calls an API' do |
| + | |
| + | let(:url) { 'https://api.stripe.com/v1/charges' } |
| + | let(:options) { |
| + | { |
| + | method: 'POST', |
| + | data: { email: 'John Doe', source: '1234567', plan: 'monthly' }, |
| + | username: 'abcdefghijkl' |
| + | } |
| + | } |
| + | |
| + | it do |
| + | expect(service.class).to receive(:post).with('/v1/charges', { |
| + | base_uri: 'https://api.stripe.com', |
| + | body: { email: 'John Doe', source: '1234567', plan: 'monthly' }, |
| + | basic_auth: { username: 'abcdefghijkl', password: nil } |
| + | }).and_return(response) |
| + | subject |
| + | end |
| + | |
| + | end |
| + | |
| end | |
| end | |