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.
@@ -1,135 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "httpi"
4
- require "savon/transport/logging"
5
- require "savon/transport/response"
6
-
7
- module Savon
8
- module Transport
9
- # HTTPI-backed HTTP transport for the default HTTP path.
10
- #
11
- # Encapsulates everything HTTPI-specific:
12
- # * header assembly
13
- # * proxy/SSL/auth/timeout configuration
14
- # * request execution
15
- class HTTPI
16
- include Logging
17
-
18
- # @param globals [Savon::GlobalOptions] the client-level options
19
- def initialize(globals)
20
- @globals = globals
21
- end
22
-
23
- # Assembles and executes a SOAP request, returning a Transport::Response.
24
- # Logs the outbound request and inbound response when logging is enabled.
25
- #
26
- # @param url [String] the SOAP endpoint URL
27
- # @param soap_headers [Hash] SOAP-level headers
28
- # @param body [String] the serialized SOAP envelope
29
- # @param locals [Savon::LocalOptions] per-request options
30
- # @return [Transport::Response]
31
- def post(url, soap_headers, body, locals)
32
- http_request = to_httpi_request(url, soap_headers, body, locals)
33
-
34
- log_request(http_request.url, http_request.headers, http_request.body) if log?
35
-
36
- http_response = ::HTTPI.post(http_request, @globals[:adapter])
37
- response = Response.new(
38
- http_response.code,
39
- http_response.headers,
40
- http_response.body,
41
- cookies: ::HTTPI::Cookie.list_from_headers(http_response.headers)
42
- )
43
-
44
- log_response(response) if log?
45
- response
46
- end
47
-
48
- # Builds a fully-configured HTTPI::Request.
49
- #
50
- # @param url [String] the SOAP endpoint URL
51
- # @param soap_headers [Hash] SOAP-level headers
52
- # @param body [String] the serialized SOAP envelope
53
- # @param locals [Savon::LocalOptions] per-request options
54
- # @return [HTTPI::Request]
55
- def to_httpi_request(url, soap_headers, body, locals)
56
- headers = {}
57
- headers.merge!(@globals[:headers]) if @globals.include?(:headers)
58
- headers.merge!(locals[:headers]) if locals.include?(:headers)
59
-
60
- # soap_headers are lowest priority
61
- soap_headers.each do |k, v| headers[k] ||= v end
62
-
63
- http_request = ::HTTPI::Request.new
64
- http_request.url = url
65
- http_request.body = body
66
- http_request.headers = headers
67
- http_request.set_cookies(locals[:cookies]) if locals[:cookies]
68
- configure_http_request(http_request)
69
- http_request
70
- end
71
-
72
- # Returns a configured HTTPI::Request for Wasabi's WSDL resolver.
73
- # Applies global headers and all transport-level options and
74
- # leaves the rest to Wasabi.
75
- #
76
- # @return [HTTPI::Request]
77
- def wsdl_request
78
- http_request = ::HTTPI::Request.new
79
- http_request.headers = @globals[:headers].dup if @globals.include?(:headers)
80
- configure_http_request(http_request)
81
- http_request
82
- end
83
-
84
- private
85
-
86
- def configure_http_request(http_request)
87
- configure_proxy(http_request)
88
- configure_timeouts(http_request)
89
- configure_ssl(http_request)
90
- configure_auth(http_request)
91
- configure_redirect_handling(http_request)
92
- end
93
-
94
- def configure_proxy(http_request)
95
- http_request.proxy = @globals[:proxy] if @globals.include?(:proxy)
96
- end
97
-
98
- def configure_timeouts(http_request)
99
- http_request.open_timeout = @globals[:open_timeout] if @globals.include?(:open_timeout)
100
- http_request.read_timeout = @globals[:read_timeout] if @globals.include?(:read_timeout)
101
- http_request.write_timeout = @globals[:write_timeout] if @globals.include?(:write_timeout)
102
- end
103
-
104
- # Configures SSL on the HTTPI::Request from all ssl globals.
105
- # SSL option reference: https://github.com/savonrb/httpi/blob/main/lib/httpi/auth/ssl.rb
106
- def configure_ssl(http_request)
107
- ssl = http_request.auth.ssl
108
- ssl.ssl_version = @globals[:ssl_version] if @globals.include?(:ssl_version)
109
- ssl.min_version = @globals[:ssl_min_version] if @globals.include?(:ssl_min_version)
110
- ssl.max_version = @globals[:ssl_max_version] if @globals.include?(:ssl_max_version)
111
- ssl.verify_mode = @globals[:ssl_verify_mode] if @globals.include?(:ssl_verify_mode)
112
- ssl.ciphers = @globals[:ssl_ciphers] if @globals.include?(:ssl_ciphers)
113
- ssl.cert_key_file = @globals[:ssl_cert_key_file] if @globals.include?(:ssl_cert_key_file)
114
- ssl.cert_key = @globals[:ssl_cert_key] if @globals.include?(:ssl_cert_key)
115
- ssl.cert_file = @globals[:ssl_cert_file] if @globals.include?(:ssl_cert_file)
116
- ssl.cert = @globals[:ssl_cert] if @globals.include?(:ssl_cert)
117
- ssl.ca_cert_file = @globals[:ssl_ca_cert_file] if @globals.include?(:ssl_ca_cert_file)
118
- ssl.ca_cert_path = @globals[:ssl_ca_cert_path] if @globals.include?(:ssl_ca_cert_path)
119
- ssl.ca_cert = @globals[:ssl_ca_cert] if @globals.include?(:ssl_ca_cert)
120
- ssl.cert_store = @globals[:ssl_cert_store] if @globals.include?(:ssl_cert_store)
121
- ssl.cert_key_password = @globals[:ssl_cert_key_password] if @globals.include?(:ssl_cert_key_password)
122
- end
123
-
124
- def configure_auth(http_request)
125
- http_request.auth.basic(*@globals[:basic_auth]) if @globals.include?(:basic_auth)
126
- http_request.auth.digest(*@globals[:digest_auth]) if @globals.include?(:digest_auth)
127
- http_request.auth.ntlm(*@globals[:ntlm]) if @globals.include?(:ntlm)
128
- end
129
-
130
- def configure_redirect_handling(http_request)
131
- http_request.follow_redirect = @globals[:follow_redirects] if @globals.include?(:follow_redirects)
132
- end
133
- end
134
- end
135
- end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "savon/log_message"
4
-
5
- module Savon
6
- module Transport
7
- # Shared logging behaviour for HTTP transports.
8
- #
9
- # Expects the including class to expose @globals (Savon::GlobalOptions)
10
- # so that log level, filters, and pretty-print settings can be accessed.
11
- #
12
- # log_request and log_response are intentionally private so that each
13
- # transport drives them from its own post method.
14
- module Logging
15
- private
16
-
17
- def log?
18
- @globals[:log]
19
- end
20
-
21
- def log_headers?
22
- @globals[:log_headers]
23
- end
24
-
25
- def logger
26
- @globals[:logger]
27
- end
28
-
29
- # Logs the outbound request at INFO (URL and optional headers)
30
- # and DEBUG (filtered/pretty-printed body).
31
- #
32
- # @param url [String] the SOAP endpoint URL
33
- # @param headers [Hash] request headers
34
- # @param body [String] the serialized SOAP envelope
35
- def log_request(url, headers, body)
36
- logger.info do "SOAP request: #{url}" end
37
- logger.info { headers_to_log(headers) } if log_headers?
38
- logger.debug { body_to_log(body) }
39
- end
40
-
41
- # Logs the inbound response at INFO (status line)
42
- # and DEBUG (headers and filtered/pretty-printed body).
43
- #
44
- # @param response [Transport::Response]
45
- def log_response(response)
46
- logger.info do "SOAP response (status #{response.code})" end
47
- logger.debug { headers_to_log(response.headers) } if log_headers?
48
- logger.debug { body_to_log(response.body) }
49
- end
50
-
51
- def headers_to_log(headers)
52
- headers.map { |key, value| "#{key}: #{value}" }.join("\n")
53
- end
54
-
55
- def body_to_log(body)
56
- LogMessage.new(body, @globals[:filters], @globals[:pretty_print_xml]).to_s
57
- end
58
- end
59
- end
60
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Savon
4
- module Transport
5
- # Transport-agnostic HTTP response value object.
6
- #
7
- # Every transport produces a Transport::Response so that higher-level code
8
- # never depends on transport-specific code. Immutable once constructed.
9
- #
10
- # The shape of #cookies is transport-specific: HTTPI responses expose an
11
- # Array of HTTPI::Cookie, while Faraday responses expose a plain Hash so
12
- # Faraday users do not depend on HTTPI types.
13
- class Response
14
- # @param code [Integer] HTTP status code
15
- # @param headers [Hash] response headers
16
- # @param body [String] response body
17
- # @param cookies [Object] parsed cookies in a transport-specific shape
18
- def initialize(code, headers, body, cookies: nil)
19
- @code = code
20
- @headers = headers
21
- @body = body
22
- @cookies = cookies
23
- end
24
-
25
- # Returns the HTTP status code.
26
- attr_reader :code
27
-
28
- # Returns the response headers hash.
29
- attr_reader :headers
30
-
31
- # Returns the response body string.
32
- attr_reader :body
33
-
34
- # Returns the parsed cookies in a transport-specific shape.
35
- # See class-level docs.
36
- attr_reader :cookies
37
-
38
- # Returns true when the HTTP status code indicates an error (>= 300).
39
- def error?
40
- @code >= 300
41
- end
42
- end
43
- end
44
- end