class Savon::Operation

Constants

SOAP_REQUEST_TYPE

Public Class Methods

create(operation_name, wsdl, globals) click to toggle source
# File lib/savon/operation.rb, line 19
def self.create(operation_name, wsdl, globals)
  if wsdl.document?
    ensure_name_is_symbol! operation_name
    ensure_exists! operation_name, wsdl
  end

  new(operation_name, wsdl, globals)
end
ensure_exists!(operation_name, wsdl) click to toggle source
# File lib/savon/operation.rb, line 28
def self.ensure_exists!(operation_name, wsdl)
  unless wsdl.soap_actions.include? operation_name
    raise UnknownOperationError, "Unable to find SOAP operation: #{operation_name.inspect}\n" \
                                 "Operations provided by your service: #{wsdl.soap_actions.inspect}"
  end
rescue Wasabi::Resolver::HTTPError => e
  raise HTTPError.new(e.response)
end
ensure_name_is_symbol!(operation_name) click to toggle source
# File lib/savon/operation.rb, line 37
def self.ensure_name_is_symbol!(operation_name)
  unless operation_name.kind_of? Symbol
    raise ArgumentError, "Expected the first parameter (the name of the operation to call) to be a symbol\n" \
                         "Actual: #{operation_name.inspect} (#{operation_name.class})"
  end
end
new(name, wsdl, globals) click to toggle source
# File lib/savon/operation.rb, line 44
def initialize(name, wsdl, globals)
  @name = name
  @wsdl = wsdl
  @globals = globals

  @logger = RequestLogger.new(globals)
end

Public Instance Methods

build(locals = {}, &block) click to toggle source
# File lib/savon/operation.rb, line 52
def build(locals = {}, &block)
  set_locals(locals, block)
  Builder.new(@name, @wsdl, @globals, @locals)
end
call(locals = {}, &block) click to toggle source
# File lib/savon/operation.rb, line 57
def call(locals = {}, &block)
  builder = build(locals, &block)

  response = Savon.notify_observers(@name, builder, @globals, @locals)
  response ||= call_with_logging build_request(builder)

  raise_expected_httpi_response! unless response.kind_of?(HTTPI::Response)

  create_response(response)
end
request(locals = {}, &block) click to toggle source
# File lib/savon/operation.rb, line 68
def request(locals = {}, &block)
  builder = build(locals, &block)
  build_request(builder)
end

Private Instance Methods

build_request(builder) click to toggle source
# File lib/savon/operation.rb, line 90
def build_request(builder)
  @locals[:soap_action] ||= soap_action
  @globals[:endpoint] ||= endpoint

  request = SOAPRequest.new(@globals).build(
    :soap_action => soap_action,
    :cookies     => @locals[:cookies],
    :headers     => @locals[:headers]
  )

  request.url = endpoint
  request.body = builder.to_s

  if builder.multipart
    request.gzip
    request.headers["Content-Type"] = ["multipart/related",
                                       "type=\"#{SOAP_REQUEST_TYPE[@globals[:soap_version]]}\"",
                                       "start=\"#{builder.multipart[:start]}\"",
                                       "boundary=\"#{builder.multipart[:multipart_boundary]}\""].join("; ")
    request.headers["MIME-Version"] = "1.0"
  end

  # TODO: could HTTPI do this automatically in case the header
  #       was not specified manually? [dh, 2013-01-04]
  request.headers["Content-Length"] = request.body.bytesize.to_s

  request
end
call_with_logging(request) click to toggle source
# File lib/savon/operation.rb, line 86
def call_with_logging(request)
  @logger.log(request) { HTTPI.post(request, @globals[:adapter]) }
end
create_response(response) click to toggle source
# File lib/savon/operation.rb, line 75
def create_response(response)
  Response.new(response, @globals, @locals)
end
endpoint() click to toggle source
# File lib/savon/operation.rb, line 131
def endpoint
  @globals[:endpoint] || @wsdl.endpoint.tap do |url|
    if @globals[:host]
      host_url = URI.parse(@globals[:host])
      url.host = host_url.host
      url.port = host_url.port
    end
  end
end
raise_expected_httpi_response!() click to toggle source
# File lib/savon/operation.rb, line 141
def raise_expected_httpi_response!
  raise Error, "Observers need to return an HTTPI::Response to mock " \
               "the request or nil to execute the request."
end
set_locals(locals, block) click to toggle source
# File lib/savon/operation.rb, line 79
def set_locals(locals, block)
  locals = LocalOptions.new(locals)
  BlockInterface.new(locals).evaluate(block) if block

  @locals = locals
end
soap_action() click to toggle source
# File lib/savon/operation.rb, line 119
def soap_action
  # soap_action explicitly set to something falsy
  return if @locals.include?(:soap_action) && !@locals[:soap_action]

  # get the soap_action from local options
  @locals[:soap_action] ||
  # with no local option, but a wsdl, ask it for the soap_action
  @wsdl.document? && @wsdl.soap_action(@name.to_sym) ||
  # if there is no soap_action up to this point, fallback to a simple default
  Gyoku.xml_tag(@name, :key_converter => @globals[:convert_request_keys_to])
end