savon 2.17.2 → 3.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/savon/header.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require "akami"
4
3
  require "gyoku"
5
4
  require "securerandom"
6
5
 
7
6
  module Savon
8
7
  class Header
8
+
9
9
  def initialize(globals, locals)
10
- @gyoku_options = { key_converter: globals[:convert_request_keys_to] }
10
+ @gyoku_options = { :key_converter => globals[:convert_request_keys_to] }
11
11
 
12
12
  @wsse_auth = locals[:wsse_auth].nil? ? globals[:wsse_auth] : locals[:wsse_auth]
13
13
  @wsse_timestamp = locals[:wsse_timestamp].nil? ? globals[:wsse_timestamp] : locals[:wsse_timestamp]
@@ -41,7 +41,7 @@ module Savon
41
41
 
42
42
  def build_header
43
43
  header =
44
- if global_header.is_a?(Hash) && local_header.is_a?(Hash)
44
+ if global_header.kind_of?(Hash) && local_header.kind_of?(Hash)
45
45
  global_header.merge(local_header)
46
46
  elsif local_header
47
47
  local_header
@@ -58,17 +58,16 @@ module Savon
58
58
  end
59
59
 
60
60
  def build_wsa_header
61
- return '' unless @globals[:use_wsa_headers]
62
-
63
- convert_to_xml({
64
- 'wsa:Action' => @locals[:soap_action],
65
- 'wsa:To' => @globals[:endpoint],
66
- 'wsa:MessageID' => "urn:uuid:#{SecureRandom.uuid}"
67
- })
61
+ return '' unless @globals[:use_wsa_headers]
62
+ convert_to_xml({
63
+ 'wsa:Action' => @locals[:soap_action],
64
+ 'wsa:To' => @globals[:endpoint],
65
+ 'wsa:MessageID' => "urn:uuid:#{SecureRandom.uuid}"
66
+ })
68
67
  end
69
68
 
70
69
  def convert_to_xml(hash_or_string)
71
- if hash_or_string.is_a? Hash
70
+ if hash_or_string.kind_of? Hash
72
71
  Gyoku.xml(hash_or_string, gyoku_options)
73
72
  else
74
73
  hash_or_string.to_s
@@ -79,11 +78,12 @@ module Savon
79
78
  wsse = Akami.wsse
80
79
  wsse.credentials(*wsse_auth) if wsse_auth
81
80
  wsse.timestamp = wsse_timestamp if wsse_timestamp
82
- if wsse_signature&.have_document?
81
+ if wsse_signature && wsse_signature.have_document?
83
82
  wsse.signature = wsse_signature
84
83
  end
85
84
 
86
85
  wsse
87
86
  end
87
+
88
88
  end
89
89
  end
@@ -2,8 +2,9 @@
2
2
 
3
3
  module Savon
4
4
  class HTTPError < Error
5
+
5
6
  def self.present?(http)
6
- http.error?
7
+ !http.success?
7
8
  end
8
9
 
9
10
  def initialize(http)
@@ -13,13 +14,14 @@ module Savon
13
14
  attr_reader :http
14
15
 
15
16
  def to_s
16
- String.new("HTTP error (#{@http.code})").tap do |str_error|
17
+ String.new("HTTP error (#{@http.status})").tap do |str_error|
17
18
  str_error << ": #{@http.body}" unless @http.body.empty?
18
19
  end
19
20
  end
20
21
 
21
22
  def to_hash
22
- { code: @http.code, headers: @http.headers, body: @http.body }
23
+ { :code => @http.status, :headers => @http.headers, :body => @http.body }
23
24
  end
25
+
24
26
  end
25
27
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require "nokogiri"
4
3
 
5
4
  module Savon
6
5
  class LogMessage
6
+
7
7
  def initialize(message, filters = [], pretty_print = false)
8
8
  @message = message
9
9
  @filters = filters
@@ -46,7 +46,8 @@ module Savon
46
46
  end
47
47
 
48
48
  def nokogiri_options
49
- @pretty_print ? { indent: 2 } : { save_with: Nokogiri::XML::Node::SaveOptions::AS_XML }
49
+ @pretty_print ? { :indent => 2 } : { :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML }
50
50
  end
51
+
51
52
  end
52
53
  end
data/lib/savon/message.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require "savon/qualified_message"
4
3
  require "gyoku"
5
4
 
6
5
  module Savon
7
6
  class Message
7
+
8
8
  def initialize(message_tag, namespace_identifier, types, used_namespaces, message, element_form_default, key_converter, unwrap)
9
9
  @message_tag = message_tag
10
10
  @namespace_identifier = namespace_identifier
@@ -18,20 +18,21 @@ module Savon
18
18
  end
19
19
 
20
20
  def to_s
21
- return @message.to_s unless @message.is_a? Hash
21
+ return @message.to_s unless @message.kind_of? Hash
22
22
 
23
23
  if @element_form_default == :qualified
24
24
  @message = QualifiedMessage.new(@types, @used_namespaces, @key_converter).to_hash(@message, [@message_tag.to_s])
25
25
  end
26
26
 
27
27
  gyoku_options = {
28
- element_form_default: @element_form_default,
29
- namespace: @namespace_identifier,
30
- key_converter: @key_converter,
31
- unwrap: @unwrap
28
+ :element_form_default => @element_form_default,
29
+ :namespace => @namespace_identifier,
30
+ :key_converter => @key_converter,
31
+ :unwrap => @unwrap
32
32
  }
33
33
 
34
34
  Gyoku.xml(@message, gyoku_options)
35
35
  end
36
+
36
37
  end
37
38
  end
@@ -1,18 +1,11 @@
1
1
  # frozen_string_literal: true
2
-
3
- require "httpi"
4
- require "savon/transport/response"
2
+ require "faraday"
5
3
 
6
4
  module Savon
7
- # A single test expectation set up by Savon's mock interface.
8
- # One expectation covers one operation call in one test.
9
- #
10
- # Records the expected operation name and message, captures what was
11
- # actually called, and either returns a synthetic response or raises
12
- # an error on mismatch.
13
5
  class MockExpectation
6
+
14
7
  def initialize(operation_name)
15
- @expected = { operation_name: operation_name }
8
+ @expected = { :operation_name => operation_name }
16
9
  @actual = nil
17
10
  end
18
11
 
@@ -22,15 +15,15 @@ module Savon
22
15
  end
23
16
 
24
17
  def returns(response)
25
- response = { code: 200, headers: {}, body: response } if response.is_a?(String)
18
+ response = { :code => 200, :headers => {}, :body => response } if response.kind_of?(String)
26
19
  @response = response
27
20
  self
28
21
  end
29
22
 
30
- def actual(operation_name, _builder, _globals, locals)
23
+ def actual(operation_name, builder, globals, locals)
31
24
  @actual = {
32
- operation_name: operation_name,
33
- message: locals[:message]
25
+ :operation_name => operation_name,
26
+ :message => locals[:message]
34
27
  }
35
28
  end
36
29
 
@@ -44,49 +37,42 @@ module Savon
44
37
  verify_message!
45
38
  end
46
39
 
47
- # Builds and returns a Transport::Response from the configured response hash.
48
- #
49
- # @return [Transport::Response]
50
- # @raise [ExpectationError] if no response was configured for this expectation
51
40
  def response!
52
41
  unless @response
53
42
  raise ExpectationError, "This expectation was not set up with a response."
54
43
  end
55
-
56
- Transport::Response.new(@response[:code], @response[:headers], @response[:body])
44
+ env = Faraday::Env.from(status: @response[:code], response_headers: @response[:headers], response_body: @response[:body])
45
+ Faraday::Response.new(env)
57
46
  end
58
47
 
59
48
  private
60
49
 
61
50
  def verify_operation_name!
62
- return if @expected[:operation_name] == @actual[:operation_name]
63
-
64
- raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation.\n" \
65
- "Received a request to the #{@actual[:operation_name].inspect} operation instead."
51
+ unless @expected[:operation_name] == @actual[:operation_name]
52
+ raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation.\n" \
53
+ "Received a request to the #{@actual[:operation_name].inspect} operation instead."
54
+ end
66
55
  end
67
56
 
68
57
  def verify_message!
69
58
  return if @expected[:message].eql? :any
59
+ unless equals_except_any(@expected[:message], @actual[:message])
60
+ expected_message = " with this message: #{@expected[:message].inspect}" if @expected[:message]
61
+ expected_message ||= " with no message."
70
62
 
71
- return if equals_except_any(@expected[:message], @actual[:message])
63
+ actual_message = " with this message: #{@actual[:message].inspect}" if @actual[:message]
64
+ actual_message ||= " with no message."
72
65
 
73
- expected_message = " with this message: #{@expected[:message].inspect}" if @expected[:message]
74
- expected_message ||= " with no message."
75
-
76
- actual_message = " with this message: #{@actual[:message].inspect}" if @actual[:message]
77
- actual_message ||= " with no message."
78
-
79
- raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation\n#{expected_message}\n" \
80
- "Received a request to the #{@actual[:operation_name].inspect} operation\n#{actual_message}"
66
+ raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation\n#{expected_message}\n" \
67
+ "Received a request to the #{@actual[:operation_name].inspect} operation\n#{actual_message}"
68
+ end
81
69
  end
82
70
 
83
71
  def equals_except_any(msg_expected, msg_real)
84
- # === allows RSpec matchers (e.g. include(:key)) to be used as expected values
85
- return true if msg_expected === msg_real # rubocop:disable Style/CaseEquality
86
- return false if msg_expected.nil? || msg_real.nil? # If both are nil has returned true
87
-
72
+ return true if msg_expected === msg_real
73
+ return false if (msg_expected.nil? || msg_real.nil?) # If both are nil has returned true
88
74
  msg_expected.each do |key, expected_value|
89
- next if expected_value == :any && msg_real.include?(key)
75
+ next if (expected_value == :any && msg_real.include?(key))
90
76
  return false if expected_value != msg_real[key]
91
77
  end
92
78
  true
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require "savon/mock"
4
3
 
5
4
  module Savon
6
5
  module SpecHelper
6
+
7
7
  class Interface
8
+
8
9
  def mock!
9
10
  Savon.observers << self
10
11
  end
@@ -26,12 +27,14 @@ module Savon
26
27
  def notify(operation_name, builder, globals, locals)
27
28
  expectation = expectations.shift
28
29
 
29
- raise ExpectationError, "Unexpected request to the #{operation_name.inspect} operation." unless expectation
30
-
31
- expectation.actual(operation_name, builder, globals, locals)
30
+ if expectation
31
+ expectation.actual(operation_name, builder, globals, locals)
32
32
 
33
- expectation.verify!
34
- expectation.response!
33
+ expectation.verify!
34
+ expectation.response!
35
+ else
36
+ raise ExpectationError, "Unexpected request to the #{operation_name.inspect} operation."
37
+ end
35
38
  rescue ExpectationError
36
39
  @expectations.clear
37
40
  raise
@@ -39,12 +42,12 @@ module Savon
39
42
 
40
43
  def verify!
41
44
  return if expectations.empty?
42
-
43
45
  expectations.each(&:verify!)
44
46
  rescue ExpectationError
45
47
  @expectations.clear
46
48
  raise
47
49
  end
50
+
48
51
  end
49
52
 
50
53
  def savon
@@ -55,5 +58,6 @@ module Savon
55
58
  super if defined? super
56
59
  savon.verify!
57
60
  end
61
+
58
62
  end
59
63
  end
data/lib/savon/mock.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module Savon
4
3
  class ExpectationError < StandardError; end
5
4
  end
data/lib/savon/model.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module Savon
4
3
  module Model
4
+
5
5
  def self.extended(base)
6
6
  base.setup
7
7
  end
@@ -28,30 +28,26 @@ module Savon
28
28
 
29
29
  # Defines a class-level SOAP operation.
30
30
  def define_class_operation(operation)
31
- method_name = operation_method_name(operation)
32
-
33
- class_operation_module.define_method(method_name) do |locals = {}|
34
- client.call operation, locals
35
- end
31
+ class_operation_module.module_eval %{
32
+ def #{StringUtils.snakecase(operation.to_s)}(locals = {})
33
+ client.call #{operation.inspect}, locals
34
+ end
35
+ }
36
36
  end
37
37
 
38
38
  # Defines an instance-level SOAP operation.
39
39
  def define_instance_operation(operation)
40
- method_name = operation_method_name(operation)
41
-
42
- instance_operation_module.define_method(method_name) do |locals = {}|
43
- self.class.public_send(method_name, locals)
44
- end
45
- end
46
-
47
- # Returns the generated Ruby method name for a SOAP operation.
48
- def operation_method_name(operation)
49
- StringUtils.snakecase(operation.to_s).to_sym
40
+ instance_operation_module.module_eval %{
41
+ def #{StringUtils.snakecase(operation.to_s)}(locals = {})
42
+ self.class.#{StringUtils.snakecase(operation.to_s)} locals
43
+ end
44
+ }
50
45
  end
51
46
 
52
47
  # Class methods.
53
48
  def class_operation_module
54
- @class_operation_module ||= Module.new do
49
+ @class_operation_module ||= Module.new {
50
+
55
51
  def client(globals = {})
56
52
  @client ||= Savon::Client.new(globals)
57
53
  rescue InitializationError
@@ -64,22 +60,26 @@ module Savon
64
60
 
65
61
  def raise_initialization_error!
66
62
  raise InitializationError,
67
- "Expected the model to be initialized with either a WSDL document or the SOAP endpoint and target namespace options.\n" \
68
- "Make sure to setup the model by calling the .client class method before calling the .global method.\n\n" \
69
- "client(wsdl: '/Users/me/project/service.wsdl') # to use a local WSDL document\n" \
70
- "client(wsdl: 'http://example.com?wsdl') # to use a remote WSDL document\n" \
71
- "client(endpoint: 'http://example.com', namespace: 'http://v1.example.com') # if you don't have a WSDL document"
63
+ "Expected the model to be initialized with either a WSDL document or the SOAP endpoint and target namespace options.\n" \
64
+ "Make sure to setup the model by calling the .client class method before calling the .global method.\n\n" \
65
+ "client(wsdl: '/Users/me/project/service.wsdl') # to use a local WSDL document\n" \
66
+ "client(wsdl: 'http://example.com?wsdl') # to use a remote WSDL document\n" \
67
+ "client(endpoint: 'http://example.com', namespace: 'http://v1.example.com') # if you don't have a WSDL document"
72
68
  end
73
- end.tap { |mod| extend(mod) }
69
+
70
+ }.tap { |mod| extend(mod) }
74
71
  end
75
72
 
76
73
  # Instance methods.
77
74
  def instance_operation_module
78
- @instance_operation_module ||= Module.new do
75
+ @instance_operation_module ||= Module.new {
76
+
79
77
  def client
80
78
  self.class.client
81
79
  end
82
- end.tap { |mod| include(mod) }
80
+
81
+ }.tap { |mod| include(mod) }
83
82
  end
83
+
84
84
  end
85
85
  end
@@ -1,42 +1,30 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require "savon/options"
4
3
  require "savon/block_interface"
4
+ require "savon/request"
5
5
  require "savon/builder"
6
6
  require "savon/response"
7
+ require "savon/request_logger"
7
8
  require "savon/http_error"
8
- require "savon/transport/httpi"
9
- require "savon/transport/faraday"
10
9
  require "mail"
10
+ require 'faraday/gzip'
11
+
11
12
 
12
13
  module Savon
13
- # Represents a single named SOAP operation.
14
- #
15
- # Bridges the SOAP layer (envelope building, action headers, multipart) and the
16
- # transport layer (execution, logging). Knows nothing about transport internals
17
- # such as proxy, SSL, or auth.
18
14
  class Operation
19
- # SOAP Content-Type values indexed by SOAP version.
20
- # SOAP 1.1 §6 (HTTP binding), SOAP 1.2 Part 2 §7.1.4 (HTTP media type)
21
- CONTENT_TYPE = {
22
- 1 => "text/xml;charset=%s",
23
- 2 => "application/soap+xml;charset=%s"
24
- }.freeze
25
-
26
- # Maps SOAP version to the base MIME type used in multipart requests.
27
- # RFC 2387 §3.1 (multipart/related Content-Type parameter)
15
+
28
16
  SOAP_REQUEST_TYPE = {
29
17
  1 => "text/xml",
30
18
  2 => "application/soap+xml"
31
- }.freeze
19
+ }
32
20
 
33
- def self.create(operation_name, wsdl, globals, transport)
21
+ def self.create(operation_name, wsdl, globals)
34
22
  if wsdl.document?
35
23
  ensure_name_is_symbol! operation_name
36
24
  ensure_exists! operation_name, wsdl
37
25
  end
38
26
 
39
- new(operation_name, wsdl, globals, transport)
27
+ new(operation_name, wsdl, globals)
40
28
  end
41
29
 
42
30
  def self.ensure_exists!(operation_name, wsdl)
@@ -45,21 +33,22 @@ module Savon
45
33
  "Operations provided by your service: #{wsdl.soap_actions.inspect}"
46
34
  end
47
35
  rescue Wasabi::Resolver::HTTPError => e
48
- raise HTTPError, e.response
36
+ raise HTTPError.new(e.response)
49
37
  end
50
38
 
51
39
  def self.ensure_name_is_symbol!(operation_name)
52
- return if operation_name.is_a? Symbol
53
-
54
- raise ArgumentError, "Expected the first parameter (the name of the operation to call) to be a symbol\n" \
55
- "Actual: #{operation_name.inspect} (#{operation_name.class})"
40
+ unless operation_name.kind_of? Symbol
41
+ raise ArgumentError, "Expected the first parameter (the name of the operation to call) to be a symbol\n" \
42
+ "Actual: #{operation_name.inspect} (#{operation_name.class})"
43
+ end
56
44
  end
57
45
 
58
- def initialize(name, wsdl, globals, transport)
59
- @name = name
60
- @wsdl = wsdl
61
- @globals = globals
62
- @transport = transport
46
+ def initialize(name, wsdl, globals)
47
+ @name = name
48
+ @wsdl = wsdl
49
+ @globals = globals
50
+
51
+ @logger = RequestLogger.new(globals)
63
52
  end
64
53
 
65
54
  def build(locals = {}, &block)
@@ -67,41 +56,24 @@ module Savon
67
56
  Builder.new(@name, @wsdl, @globals, @locals)
68
57
  end
69
58
 
70
- # Executes the SOAP operation and returns a Savon::Response.
71
- #
72
- # Observer short-circuit: if any registered observer returns a
73
- # Transport::Response (or legacy HTTPI::Response), the HTTP call
74
- # is skipped and that response is used directly.
75
59
  def call(locals = {}, &block)
76
- builder = build(locals, &block)
60
+ builder = build(locals, &block)
61
+
77
62
  response = Savon.notify_observers(@name, builder, @globals, @locals)
63
+ response ||= call_with_logging build_connection(builder)
78
64
 
79
- response =
80
- if response.nil?
81
- body = builder.to_s
82
- headers = soap_headers(builder)
83
- @transport.post(endpoint.to_s, headers, body, @locals)
84
- else
85
- normalize_observer_response(response)
86
- end
65
+ raise_expected_faraday_response! unless response.kind_of?(Faraday::Response)
87
66
 
88
67
  create_response(response)
89
68
  end
90
69
 
91
- # Builds and returns the HTTPI::Request that would be sent for this
92
- # operation, without executing it. Useful for inspection and debugging.
93
- # Not supported with transport: :faraday.
94
70
  def request(locals = {}, &block)
95
- if @globals[:transport] == :faraday
96
- raise ArgumentError, "#request returns an HTTPI::Request and is not supported " \
97
- "with transport: :faraday. Use client.faraday to configure " \
98
- "the connection"
99
- end
100
-
101
71
  builder = build(locals, &block)
102
- # Build the body before soap_headers - see #call.
103
- body = builder.to_s
104
- @transport.to_httpi_request(endpoint.to_s, soap_headers(builder), body, @locals)
72
+ connection = build_connection(builder)
73
+ connection.build_request(:post) do |req|
74
+ req.url(@globals[:endpoint])
75
+ req.body = @locals[:body]
76
+ end
105
77
  end
106
78
 
107
79
  private
@@ -117,33 +89,47 @@ module Savon
117
89
  @locals = locals
118
90
  end
119
91
 
120
- # Assembles the SOAP-level request headers for the given builder.
121
- #
122
- # Our responsibility regardless of transport:
123
- # * Content-Type (SOAP 1.1 §6 / SOAP 1.2 Part 2 §7.1.4)
124
- # * SOAPAction (SOAP 1.1 §6.1.1)
125
- # * Multipart Content-Type (RFC 2387), MIME-Version (RFC 2045 §4), Accept-Encoding (RFC 9110 §12.5.3)
126
- def soap_headers(builder)
127
- headers = {}
128
-
129
- if builder.multipart
130
- # RFC 2387 §3 (multipart/related) - SOAP envelope is the root body part
131
- headers["Content-Type"] = [
132
- "multipart/related",
133
- "type=\"#{SOAP_REQUEST_TYPE[@globals[:soap_version]]}\"",
134
- "start=\"#{builder.multipart[:start]}\"",
135
- "boundary=\"#{builder.multipart[:multipart_boundary]}\""
136
- ].join("; ")
137
- headers["MIME-Version"] = "1.0"
138
- headers["Accept-Encoding"] = "gzip,deflate"
139
- else
140
- headers["Content-Type"] = CONTENT_TYPE[@globals[:soap_version]] % @globals[:encoding]
92
+ def call_with_logging(connection)
93
+ ntlm_auth = handle_ntlm(connection) if @globals.include?(:ntlm)
94
+ @logger.log_response(connection.post(@globals[:endpoint]) { |request|
95
+ request.body = @locals[:body]
96
+ request.headers['Authorization'] = "NTLM #{auth.encode64}" if ntlm_auth
97
+ @logger.log_request(request)
98
+ })
99
+ end
100
+
101
+ def handle_ntlm(connection)
102
+ ntlm_message = Net::NTLM::Message
103
+ response = connection.get(@globals[:endpoint]) do |request|
104
+ request.headers['Authorization'] = 'NTLM ' + ntlm_message::Type1.new.encode64
105
+ end
106
+ challenge = response.headers['www-authenticate'][/(?:NTLM|Negotiate) (.*)$/, 1]
107
+ message = ntlm_message::Type2.decode64(challenge)
108
+ message.response([:user, :password, :domain].zip(@globals[:ntlm]).to_h)
109
+ end
110
+
111
+ def build_connection(builder)
112
+ @globals[:endpoint] ||= endpoint
113
+ @locals[:soap_action] ||= soap_action
114
+ @locals[:body] = builder.to_s
115
+ @connection = SOAPRequest.new(@globals).build(
116
+ :soap_action => soap_action,
117
+ :cookies => @locals[:cookies],
118
+ :headers => @locals[:headers]
119
+ ) do |connection|
120
+ if builder.multipart
121
+ connection.request :gzip
122
+ connection.headers["Content-Type"] = %W[multipart/related
123
+ type="#{SOAP_REQUEST_TYPE[@globals[:soap_version]]}",
124
+ start="#{builder.multipart[:start]}",
125
+ boundary="#{builder.multipart[:multipart_boundary]}"].join("; ")
126
+ connection.headers["MIME-Version"] = "1.0"
127
+ end
128
+
129
+ connection.headers["Content-Length"] = @locals[:body].bytesize.to_s
141
130
  end
142
131
 
143
- action = soap_action
144
- headers["SOAPAction"] = %("#{action}") if action
145
132
 
146
- headers
147
133
  end
148
134
 
149
135
  def soap_action
@@ -152,10 +138,10 @@ module Savon
152
138
 
153
139
  # get the soap_action from local options
154
140
  @locals[:soap_action] ||
155
- # with no local option, but a wsdl, ask it for the soap_action
156
- @wsdl.document? && @wsdl.soap_action(@name.to_sym) ||
157
- # if there is no soap_action up to this point, fallback to a simple default
158
- Gyoku.xml_tag(@name, key_converter: @globals[:convert_request_keys_to])
141
+ # with no local option, but a wsdl, ask it for the soap_action
142
+ @wsdl.document? && @wsdl.soap_action(@name.to_sym) ||
143
+ # if there is no soap_action up to this point, fallback to a simple default
144
+ Gyoku.xml_tag(@name, :key_converter => @globals[:convert_request_keys_to])
159
145
  end
160
146
 
161
147
  def endpoint
@@ -168,26 +154,10 @@ module Savon
168
154
  end
169
155
  end
170
156
 
171
- # Normalizes an observer return value into a Transport::Response.
172
- #
173
- # Accepts Transport::Response directly (current contract), wraps
174
- # HTTPI::Response with a deprecation warning (legacy observer support),
175
- # and raises on anything else.
176
- def normalize_observer_response(response)
177
- return response if response.is_a?(Transport::Response)
178
-
179
- if response.is_a?(HTTPI::Response)
180
- warn "Observers returning HTTPI::Response is deprecated - return Savon::Transport::Response instead.", uplevel: 1
181
- return Transport::Response.new(
182
- response.code,
183
- response.headers,
184
- response.body,
185
- cookies: HTTPI::Cookie.list_from_headers(response.headers)
186
- )
187
- end
188
-
189
- raise Error, "Observers need to return a Savon::Transport::Response " \
190
- "to mock the request or nil to execute the request."
157
+ def raise_expected_faraday_response!
158
+ raise Error, "Observers need to return a Faraday::Response to mock " \
159
+ "the request or nil to execute the request."
191
160
  end
161
+
192
162
  end
193
163
  end