require 'stockboy/provider' require 'stockboy/string_pool' require 'savon' module Stockboy::Providers # Fetch data from a SOAP endpoint # # Backed by Savon gem, see savon for full configuration options: extra # options are passed through. # class SOAP < Stockboy::Provider include Stockboy::StringPool # @!group Options # # These options correspond to Savon client options # URL with the WSDL document # # @!attribute [rw] wsdl # @return [String] # @example # wsdl "http://example.com/api/soap?wsdl" # dsl_attr :wsdl # Maximum time to establish a connection # # @!attribute [rw] open_timeout # @return [Integer] # @example # open_timeout 10 # dsl_attr :open_timeout # Maximum time to read data from connection # # @!attribute [rw] read_timeout # @return [Integer] # @example # read_timeout 10 # dsl_attr :read_timeout # The name of the request, see your SOAP documentation # # @!attribute [rw] request # @return [String] # @example # request "allItemsDetails" # dsl_attr :request # @return [Symbol] # @example # env_namespace :soapenv # dsl_attr :env_namespace # @return [String] # @!attribute [rw] namespace # Optional if specified in WSDL # dsl_attr :namespace # @return [Hash] # @!attribute [rw] namespaces # Optional if specified in WSDL # dsl_attr :namespaces # @return [String] # @!attribute [rw] namespace_id # Optional if specified in WSDL # dsl_attr :namespace_id # @return [String] # @!attribute [rw] endpoint # Optional if specified in WSDL # dsl_attr :endpoint # Hash of message options passed in the request, often includes # credentials and query options. # # @!attribute [rw] message # @return [Hash] # @example # message "clientId" => "12345", "updatedSince" => "2012-12-12" # dsl_attr :message # Message tag name # # @!attribute [rw] message_tag # @return [String] # @example # message_tag "GetResult" # dsl_attr :message_tag # @return [String] # @example # soap_action "urn:processMessage" # dsl_attr :soap_action # XML string to override the Soap headers # # @!attribute [rw] soap_header # @return [String] # @example # soap_header "<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">..." # dsl_attr :soap_header # @return [Hash] # @example # attributes {} # dsl_attr :attributes # Change the default response type, default :hash # # @!attribute [rw] response_format # @return [Symbol] # @example # response_format :xml # dsl_attr :response_format # Hash of optional HTTP request headers # # @!attribute [rw] headers # @return [Hash] # @example # headers "X-ClientKey" => "12345" # dsl_attr :headers # Array of WSSE Auth values # # @!attribute [rw] wsse_auth # @return [Array] # @example # wsse_auth ["Username", "Password"] # dsl_attr :wsse_auth # @!endgroup # Initialize a new SOAP provider # def initialize(opts={}, &block) super @response_format = opts[:response_format] || :hash DSL.new(self).instance_eval(&block) if block_given? end # Connection object to the configured SOAP endpoint # # @return [Savon::Client] # def client @client ||= Savon.client() @client.globals.open_timeout(open_timeout) if open_timeout @client.globals.read_timeout(read_timeout) if read_timeout yield @client if block_given? @client end private def opts = if wsdl {wsdl: wsdl} elsif endpoint {endpoint: endpoint} end opts[:open_timeout] = open_timeout if open_timeout opts[:read_timeout] = read_timeout if read_timeout opts[:logger] = logger opts[:log] = logger.debug? opts[:convert_response_tags_to] = ->(tag) { string_pool(tag) } opts[:namespace] = namespace if namespace opts[:namespaces] = namespaces if namespaces opts[:namespace_identifier] = namespace_id if namespace_id opts[:env_namespace] = env_namespace if env_namespace opts[:headers] = headers if headers opts[:wsse_auth] = wsse_auth if wsse_auth opts end def validate errors << "endpoint or wsdl must be specified" if endpoint.blank? unless wsdl errors.blank? end def fetch_data with_string_pool do response = client.call( @request, message: , message_tag: , soap_action: soap_action, soap_header: soap_header, attributes: attributes ) @data = case response_format when :xml response.xml else response.body end end end end end