require "wasabi/document"
require "httpi/request"
require "akami"
require "savon/soap/xml"
require "savon/soap/request"
require "savon/soap/response"
require "savon/soap/request_builder"
module Savon
class Client
def initialize(wsdl_document = nil, &block)
self.config = Savon.config.clone
wsdl.document = wsdl_document if wsdl_document
process 1, &block if block
wsdl.request = http
end
attr_accessor :config
def wsdl
@wsdl ||= Wasabi::Document.new
end
def http
@http ||= HTTPI::Request.new
end
def wsse
@wsse ||= Akami.wsse
end
def request(*args, &block)
raise ArgumentError, "Savon::Client#request requires at least one argument" if args.empty?
options = (args)
request_builder = SOAP::RequestBuilder.new(options.delete(:input), options)
request_builder.wsdl = wsdl
request_builder.http = http.dup
request_builder.wsse = wsse.dup
request_builder.config = config.dup
post_configuration = lambda { process(0, request_builder, &block) if block }
response = request_builder.request(&post_configuration).response
http.set_cookies(response.http)
if wsse.verify_response
WSSE::VerifySignature.new(response.http.body).verify!
end
response
end
private
def (args)
attributes = Hash === args.last ? args.pop : {}
body = attributes.delete(:body)
soap_action = attributes.delete(:soap_action)
namespace_identifier = args.size > 1 ? args.shift.to_sym : nil
input = args.first
remove_blank_values(
:namespace_identifier => namespace_identifier,
:input => input,
:attributes => attributes,
:body => body,
:soap_action => soap_action
)
end
def process(offset = 0, instance = self, &block)
block.arity > 0 ? yield_objects(offset, instance, &block) : evaluate(instance, &block)
end
def yield_objects(offset, instance, &block)
to_yield = [:soap, :wsdl, :http, :wsse]
yield *(to_yield[offset, block.arity].map { |obj_name| instance.send(obj_name) })
end
def evaluate(instance, &block)
original_self = eval "self", block.binding
proxy = Object.new
proxy.instance_eval do
class << self
attr_accessor :original_self, :instance
end
def method_missing(method, *args, &block)
instance.send(method, *args, &block)
rescue NoMethodError
original_self.send(method, *args, &block)
end
end
proxy.instance = instance
proxy.original_self = original_self
proxy.instance_eval &block
end
def remove_blank_values(hash)
hash.delete_if { |_, value| value.respond_to?(:empty?) ? value.empty? : !value }
end
end
end