savon 2.17.4 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bba4a9ced6c62286d20de586b56ce7263413fa5e4b51771e87fded4c2433f39
4
- data.tar.gz: 9327a65ee629c258691084a822b635738b4d31ea38c5bd38f8e3399f11b16cd9
3
+ metadata.gz: 3f58a5268715a082369bc199231506447defea5f760fae67cb51507a9011836c
4
+ data.tar.gz: d349d7d546fb236e45f433047bd575dd6f6ec206254707094f02420ec58dfc07
5
5
  SHA512:
6
- metadata.gz: a1d50a4b5f588cc1e094189f41aada85a2bbecf7b6dbf92b27c6041d7b3eb882808ec69c0d2f0e907cc572cea73c17bad18f82d74c400e4019836200ce1255e9
7
- data.tar.gz: 9a61b3a21ae8a2c16761fb851c85355cd3e2575e540447ec7ac0fa5cbd42ae5bfa456c26813a5dce907fb9924f2cd6dece545f841f65a970a87445123fe90005
6
+ metadata.gz: 91d6cd948edbb82b643fa5aaeef265dcfeef5037459478f0815f01bdacbe04cb159165301a9f0ebc75fd897470ff2a0b51de1fa256123843698a14925f5ebf43
7
+ data.tar.gz: 3a9fe95352e4f85e9e88f7eaffba5fb04df58085380ed7c62e8c0f31c0b110b5127c494125f373e97489c789991b6c1271e68df000606c3e1a3311a17edc951a
data/CHANGELOG.md CHANGED
@@ -1,113 +1,22 @@
1
1
  # Savon changelog
2
2
 
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## [2.17.4] - 2026-07-03
9
-
10
- **Restore WS-Addressing headers and fix `:wsse_signature` resolution**
11
-
12
- ### Fixed
13
-
14
- * **WS-Addressing headers are populated from the WSDL again** ([#1057](https://github.com/savonrb/savon/issues/1057)). With `use_wsa_headers: true` and no explicit `:soap_action` or `:endpoint`, Savon emitted empty `<wsa:Action xsi:nil="true"/>` and `<wsa:To xsi:nil="true"/>` elements instead of the operation's SOAPAction and service endpoint. Up to 2.16.0 those values were populated as a side effect of building the HTTP request. The 2.17.0 transport refactor removed that step.
15
- * **A global `:host` override no longer rewrites the WSDL's endpoint.** Resolving the request endpoint with `:host` set replaced host and port of the parsed WSDL address in place, visible as a permanently changed `client.wsdl.endpoint` after the first call. Endpoint and SOAPAction resolution moved into `Savon::EffectiveOptions`, which applies the override to a copy and never touches the WSDL document.
16
- * **A local `:wsse_signature` no longer crashes when set to `false`.** Passing `wsse_signature: false` to a call raised `NoMethodError: undefined method 'have_document?' for false` while building the WSSE header. The envelope builder and the SOAP header also resolved the option with different rules, so they could disagree on which signature applies. Both now read it through `Savon::EffectiveOptions`, the one place that resolves options settable in both the global and the local scope. A falsy local `:wsse_signature` falls back to the global one. Setting a signature object in either scope is unaffected.
17
-
18
- ### Deprecated
19
-
20
- * **`Savon::Builder::WSA_NAMESPACE`.** WS-Addressing emission moved into `Savon::Addressing`, which owns the namespace as `Savon::Addressing::NAMESPACE`. The constant on `Savon::Builder` stays available as an alias and will be removed in Savon 3.
21
-
22
- ## [2.17.3] - 2026-06-23
23
-
24
- **Fix Savon::HTTPError compatibility with Faraday transport**
25
-
26
- ### Fixed
27
-
28
- * **`Savon::HTTPError` works with the Faraday transport** ([#1050](https://github.com/savonrb/savon/issues/1050)). When a the WSDL could not be fetched under `transport: :faraday`, `Savon::HTTPError#to_s` and `#to_hash` raised `NoMethodError: undefined method 'code'` because they were handed a raw `Faraday::Response`, which exposes `#status` rather than `#code`. Transports now normalize adapter-specific response objects into `Savon::Transport::Response` before they reach `Savon::HTTPError`.
29
-
30
- ## [2.17.2] - 2026-06-10
31
-
32
- **Fix CVE-2026-53510 and restore 2.17.0 cookie regressions**
33
-
34
- ### Fixed
35
-
36
- * **Fix CVE-2026-53510** `Savon::Model` generated SOAP operation methods by interpolating operation names into Ruby source passed to `module_eval`. An attacker who can control the operation names of a WSDL, can inject Ruby code that executes in the application process. This affects only the `.all_operations` class method provided by `Savon::Model` to automatically register all operations provided by the WSDL. Configuring `Savon::Model` with trusted operation names via `.operations` is safe. Thanks to @connorshea for securely disclosing this, providing a proof and a great report.
37
- * **`:cookies` request option works again.** The 2.17.0 transport refactor reimplemented cookie handling on top of `Array#map`, which broke callers passing an object that responds to `#cookies` and lost cookie-name de-duplication via `HTTPI::CookieStore`. The HTTPI transport delegates to `HTTPI::Request#set_cookies` again, restoring both shapes.
38
- * **`response.http.cookies` works again.** 2.17.0's `Savon::Transport::Response` only exposed `code`, `headers`, and `body`. The HTTPI transport now returns `Array<HTTPI::Cookie>` (matching 2.12.1). The Faraday transport returns `Hash<String, String>` so Faraday callers do not need HTTPI types.
39
- * **`:attachments` now works with a user-supplied `:xml` envelope** ([#761](https://github.com/savonrb/savon/pull/761)). Multipart support shipped in 2.13.0 but only wrapped envelopes Savon built itself. When a caller passed their own `:xml`, attachments were silently dropped.
40
-
41
- ### Added
42
-
43
- * **Faraday `:cookies` option accepts a `String` or `Hash`.** Strings are used verbatim, Hashes are formatted as `"name=value; name=value"`. Round-trippable with the Faraday response shape.
44
- * **Three Nori response-parsing options exposed as Savon globals:** `:empty_tag_value` (default `nil`), `:convert_dashes_to_underscores` (default `true`), and `:scrub_xml` (default `true`). Defaults match Nori's own for backwards compatibility.
45
-
46
- ### Changed
47
-
48
- * **Minimum Nori version is now `~> 2.7`** (was `~> 2.4`). Needed for the new parsing options (`:empty_tag_value` arrived in Nori 2.6.0, `:scrub_xml` in 2.7.0). The 2.5–2.7 series also brings fixes callers benefit from automatically: invalid byte sequences parse instead of raising, REXML no longer turns `&lt;` inside CDATA into `<`, `xs:date`/`xs:time`/`xs:dateTime` typecasting was corrected, and Nori stopped monkey-patching `String` and `Object`.
49
- * **Faraday migration hints are now value-aware and verified.** Each hint prints the caller's actual option value and spells out the full gem/require/setup where needed. Fixed several incorrect examples and added tests to verify every hint.
50
-
51
- ### Deprecated
52
-
53
- * Deprecated the global and local `:multipart` options. They have been no-ops since v2.13.0. Specifically since commit 4e7ae5e. Savon detects multipart responses by checking the `Content-Type` header.
54
-
55
- ## [2.17.1] - 2026-05-21
56
-
57
- ### Fixed
58
-
59
- * [#1008](https://github.com/savonrb/savon/pull/1008) - The HTTPI and Faraday transports no longer set an explicit `Content-Length` request header. The underlying HTTP library already computes it from the body. Sending it as well produced a duplicate header on adapters that do not deduplicate (e.g. httpclient), which some servers reject.
60
- * Requests using `attachments` were sent with a plain `text/xml` Content-Type instead of `multipart/related`. The 2.17.0 transport refactor assembled the request headers before the multipart body was built, leaving `Builder#multipart` empty at header time, so servers received a multipart body labelled as plain XML. 2.16.x and earlier are unaffected.
61
-
62
- ## [2.17.0] - 2026-05-19
63
-
64
- **Add opt-in Faraday transport**
65
-
66
- Callers who set `transport: :faraday` get a memoized `Faraday::Connection` via `client.faraday` and full control over middleware, SSL, auth, and timeouts. Callers who do not set this option see no behavior change. HTTPI remains the default for 2.x.
67
-
68
- ### Added
69
-
70
- * `transport: :faraday` global option. Defaults to `:httpi` (#992).
71
- * `client.faraday` returns a memoized `Faraday::Connection` for configuring middleware, SSL, auth, and timeouts when using the Faraday transport.
72
- * `Savon.client` raises if `transport: :faraday` is set but the faraday gem is not installed, or if any httpi-specific global option (`proxy`, timeouts, `ssl`, auth, `adapter`) is set alongside it. All conflicts are reported with their Faraday equivalents.
73
-
74
- ### Changed
75
-
76
- * Observers must return `Savon::Transport::Response` (or `nil`) instead of `HTTPI::Response`.
77
-
78
- ### Deprecated
79
-
80
- * The HTTPI transport (currently the default) and all HTTPI-specific global options enumerated in `Savon::FaradayMigrationHint::OPTIONS` (`proxy`, `open_timeout`, `read_timeout`, `write_timeout`, the `ssl_*` family, `basic_auth`, `digest_auth`, `ntlm`, `follow_redirects`, `adapter`) will be removed in 3.0. Migrate to `transport: :faraday`. `FaradayMigrationHint` shows the Faraday equivalent for each option.
81
- * Returning `HTTPI::Response` from observers emits a deprecation warning and will be removed in 3.0. Return `Savon::Transport::Response` instead.
82
-
83
- The Faraday transport unblocks:
84
-
85
- * redirect following for WSDL fetches via `faraday-follow-redirects` middleware (#1033, savonrb/wasabi#18)
86
- * digest authentication via `faraday-digestauth` middleware (#1021, savonrb/httpi#250)
87
- * proxy authentication with special characters in passwords (#941)
88
- * and setting an `Accept` header for WSDL requests from Rails apps (savonrb/wasabi#115)
89
-
90
- ## [2.16.0] - 2026-05-18
91
-
92
- **Restore compatibility**
93
-
94
- If you stayed on 2.12.1 because a later version broke something, this release is for you. The fixes below target the most commonly reported upgrade blockers. Existing code should work without modification.
95
-
96
- ### Fixed
97
-
98
- * Restore `Savon::Response#hash` removed in 2.14.0 (#985). Callers on 2.12.1 that use `response.hash` get the soap body back instead of Ruby's integer object id.
99
- * Require wasabi >= 5.1.0 (#1015, #1016). Wasabi 4.x used message names as soap body element names and SOAPAction header values instead of operation names (savonrb/wasabi#122), causing servers to return a fault or reject the action for operations whose message name carried an `In` suffix.
100
- * Stop dumping all WSDL namespaces into every soap envelope (#1014, #942). 2.13.0 injected every namespace from the entire WSDL document into each request, including structural ones that have no place in a request body. Strict servers reject envelopes with unexpected or duplicate declarations.
101
- * Raise a proper `SOAPFault` instead of a raw exception when `soap:Fault` contains invalid encoding (#923).
102
- * `SOAPFault.present?` was ignoring its `xml` argument and always operating on the instance's own body.
103
-
104
- ### Changed
105
-
106
- * Added Ruby 3.4 (#1024) and Ruby 4.0 (#1039) to the CI test matrix.
107
-
108
- ### Deprecated
109
-
110
- * `Savon::Response#hash` emits a deprecation warning on each call. Use `#full_hash` going forward. Will be removed in 3.0.
3
+ ## Unreleased
4
+ * Add your PR changelog line here
5
+
6
+ ## 3.0.0.rc1 (2024-07-15)
7
+
8
+ * Use Faraday instead of HTTPI
9
+ * BC BREAKING Cookies are handled differently now
10
+ * BC BREAKING Multiple pieces of functionality will rely on faraday libraries to be provided by the consuming codebase
11
+ * BC BREAKING Adapter overrides now utilize the faraday model
12
+ * BC BREAKING Multiple hard deprecations due to a lack of feature parity between Faraday and HTTPI
13
+ * Deprecates digest auth
14
+ * Deprecates ssl_cert_key_file auth, upgrade path is to read the key
15
+ in and provide it
16
+ * Deprecates encrypted ssl keys, upgrade path is to
17
+ decrypt the key and pass it to faraday in code
18
+ * Deprecates providing a ca cert, upgrade path is to provide a ca cert file
19
+ * deprecates overriding ssl ciphers, as faraday does not support this
111
20
 
112
21
  ## 2.15.1 (2024-07-08)
113
22
 
@@ -1261,10 +1170,3 @@ Pay attention to the following list and read the updated Wiki: http://wiki.githu
1261
1170
  ## 0.5.0 (2009-11-29)
1262
1171
 
1263
1172
  * Complete rewrite and public release.
1264
-
1265
- [2.17.4]: https://github.com/savonrb/savon/compare/v2.17.3...v2.17.4
1266
- [2.17.3]: https://github.com/savonrb/savon/compare/v2.17.2...v2.17.3
1267
- [2.17.2]: https://github.com/savonrb/savon/compare/v2.17.1...v2.17.2
1268
- [2.17.1]: https://github.com/savonrb/savon/compare/v2.17.0...v2.17.1
1269
- [2.17.0]: https://github.com/savonrb/savon/compare/v2.16.0...v2.17.0
1270
- [2.16.0]: https://github.com/savonrb/savon/compare/v2.15.1...v2.16.0
data/README.md CHANGED
@@ -2,88 +2,88 @@
2
2
 
3
3
  Heavy metal SOAP client
4
4
 
5
+ [Documentation](https://www.rubydoc.info/gems/savon/) | [Support](https://stackoverflow.com/questions/tagged/savon) |
6
+ [Mailing list](https://groups.google.com/forum/#!forum/savonrb) | [Twitter](http://twitter.com/savonrb)
7
+
5
8
  [![Ruby](https://github.com/savonrb/savon/actions/workflows/ci.yml/badge.svg)](https://github.com/savonrb/savon/actions/workflows/ci.yml)
6
9
  [![Gem Version](https://badge.fury.io/rb/savon.svg)](http://badge.fury.io/rb/savon)
10
+ [![Code Climate](https://codeclimate.com/github/savonrb/savon.svg)](https://codeclimate.com/github/savonrb/savon)
7
11
  [![Coverage Status](https://coveralls.io/repos/savonrb/savon/badge.svg)](https://coveralls.io/r/savonrb/savon)
8
12
 
9
- Savon is a SOAP client for Ruby. [SOAP is the protocol](https://www.w3.org/TR/soap/) spoken by many enterprise systems. When they hand you a WSDL URL or file instead of a REST spec, it's SOAP. Savon reads the WSDL, maps available operations to Ruby symbols, converts Ruby hashes to SOAP envelopes and turns XML responses into hashes you can work with.
10
-
11
- Full documentation is at [savonrb.com](https://savonrb.com).
13
+ If you're reading this on GitHub, note that this README is for the main branch and that features/changes described here might not correspond to your version. You can find the documentation for your release [at rubydoc.info](https://www.rubydoc.info/find/gems?q=savon).
12
14
 
13
15
  ## Installation
14
16
 
15
- ```ruby
16
- gem 'savon', '~> 2.17'
17
+ Savon is available through [Rubygems](http://rubygems.org/gems/savon) and can be installed via:
18
+
19
+ ```
20
+ $ gem install savon
17
21
  ```
18
22
 
19
- ## Usage
23
+ or add it to your Gemfile like this:
20
24
 
21
- ```ruby
25
+ ```
26
+ gem 'savon', '~> 3.0.0'
27
+ ```
28
+
29
+ ## Usage example
30
+
31
+ ``` ruby
22
32
  require 'savon'
23
33
 
24
- # Point Savon to a local or remote WSDL document
25
- client = Savon.client(wsdl: 'https://service.example.com?wsdl')
34
+ # create a client for the service
35
+ client = Savon.client(wsdl: 'http://service.example.com?wsdl')
36
+
37
+ # or: create a client with a wsdl provided as a string
38
+ client = Savon.client do |config|
39
+ wsdl_content = File.read("/path/to/wsdl")
40
+ config.wsdl wsdl_content
41
+ end
26
42
 
27
- # See what the service exposes
28
43
  client.operations
29
- # => [:find_user, :create_user]
44
+ # => [:find_user, :list_users]
30
45
 
31
- # Make a request and work with the response
46
+ # call the 'findUser' operation
32
47
  response = client.call(:find_user, message: { id: 42 })
33
- response.body[:find_user_response]
34
- # => { id: 42, name: "Hoff" }
35
48
 
36
- # Savon raises a Savon::SOAPFault when the server returns a SOAP fault
37
- rescue Savon::SOAPFault => e
38
- puts e.to_hash.dig(:fault, :faultstring)
49
+ response.body
50
+ # => { find_user_response: { id: 42, name: 'Hoff' } }
39
51
  ```
40
52
 
41
- Enable logging to see the raw SOAP envelopes. That's probably the single most useful thing while getting a new integration working:
53
+ For more examples, you should check out the
54
+ [integration tests](https://github.com/savonrb/savon/tree/version2/spec/integration).
42
55
 
43
- ```ruby
44
- client = Savon.client(
45
- wsdl: 'https://service.example.com?wsdl',
46
- pretty_print_xml: true,
47
- log: true
48
- )
49
- ```
50
-
51
- ### Authentication
52
-
53
- Most enterprise services require authentication. Common options:
54
-
55
- ```ruby
56
- # HTTP basic auth
57
- Savon.client(wsdl: '...', basic_auth: ['user', 'secret'])
56
+ ## Upgrading from v2.x to v3.x
58
57
 
59
- # WS-Security (WSSE)
60
- Savon.client(wsdl: '...', wsse_auth: ['user', 'secret', :digest], wsse_timestamp: true)
61
- ```
62
-
63
- See [Authentication](https://savonrb.com/version2/globals.html) on the website for HTTP digest, NTLM, and certificate-based options.
58
+ See [UPGRADING.md](UPGRADING.md) for more information.
64
59
 
65
- ### Transport
60
+ ## Ruby version support
66
61
 
67
- Savon uses [HTTPI](https://github.com/savonrb/httpi) for HTTP by default. Since v2.17.0 you can opt-in to use Faraday by passing `transport: :faraday` which exposes the Faraday connection at `client.faraday` for you to configure. Savon is only adding some SOAP-specifics on top.
62
+ Every savon release is tested with contemporary supported versions of ruby. Historical compatibility information:
68
63
 
69
- ## Ruby support
64
+ * `main` - same support as Ruby
65
+ * 2.15.x - MRI 3.0, 3.1, 3.2, 3.3
66
+ * 2.13.x, 2.14.x - MRI 2.7, 3.0, 3.1
67
+ * 2.12.x - MRI 2.2, 2.3, 2.4, 2.5
68
+ * 2.11.x - MRI 2.0, 2.1, 2.2, and 2.3
70
69
 
71
- Savon 2.x requires Ruby >= 3.0.0, kept as the lower bound for backward compatibility. Note that Ruby 3.0–3.3 are EOL or security-only. Ruby 3.4+ is the minimum version with active maintenance.
70
+ If you are running MRI 1.8.7, try a 2.6.x release.
72
71
 
73
- ## Versioning & stability
72
+ Most changes are not backported to older versions of savon, or unsupported ruby versions.
74
73
 
75
- Savon follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). The changelog format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
74
+ ## Running tests
76
75
 
77
- **The 2.x line is anchored on 2.12.1.** Every 2.x release is supposed to be safe to upgrade to from 2.12.1, and anything that worked in 2.12.1 keeps working. We do not remove or rename public APIs in the 2.x line. New behavior is opt-in and requires an explicit option change. If you found a problem with that, please let us know.
78
-
79
- We only soft-deprecate APIs we plan to remove. The `Deprecated` sections of the [changelog](CHANGELOG.md) list every API that is planned to be removed with version 3.0.
76
+ ```bash
77
+ $ bundle install
78
+ $ bundle exec rspec
79
+ ```
80
80
 
81
- Callers on 2.13.0–2.15.x may see specific post-2.12.1 behaviors restored to the 2.12.1 contract. This is intentional.
81
+ ## FAQ
82
82
 
83
- ## Known limitations
83
+ * URI::InvalidURIError -- if you see this error, then it is likely that the http client you are using cannot parse the URI for your WSDL. Try `gem install httpclient` or add it to your `Gemfile`.
84
+ - See https://github.com/savonrb/savon/issues/488 for more info
84
85
 
85
- **WSDL imports are not followed.** Savon parses only the root WSDL document via [Wasabi](https://github.com/savonrb/wasabi). Messages, port types, and bindings defined in imported files are invisible to Savon. If you control the WSDL, merge the imported elements into the root document and pass that to Savon as a string. If you need full import support, the [WSDL](https://rubygems.org/gems/wsdl) gem is an alternative.
86
86
 
87
- ## Contributing
87
+ ## Documentation
88
88
 
89
- See [CONTRIBUTING.md](CONTRIBUTING.md). MIT licensed.
89
+ Please be sure to [read the documentation](https://www.rubydoc.info/github/savonrb/savon/).
data/Rakefile CHANGED
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "bundler/gem_tasks"
4
2
  require "rspec/core/rake_task"
5
3
 
@@ -12,7 +10,5 @@ RSpec::Core::RakeTask.new "spec:integration" do |t|
12
10
  t.pattern = "spec/integration/**/*_spec.rb"
13
11
  end
14
12
 
15
- desc "Alias for spec task"
16
- task test: :spec
17
-
18
- task default: :spec
13
+ task :default => :spec
14
+ task :test => :spec
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module Savon
4
3
  class BlockInterface
4
+
5
5
  def initialize(target)
6
6
  @target = target
7
7
  end
8
8
 
9
9
  def evaluate(block)
10
- if block.arity.positive?
10
+ if block.arity > 0
11
11
  block.call(@target)
12
12
  else
13
- @original = eval("self", block.binding, __FILE__, __LINE__)
13
+ @original = eval("self", block.binding)
14
14
  instance_eval(&block)
15
15
  end
16
16
  end
@@ -22,5 +22,6 @@ module Savon
22
22
  rescue NoMethodError
23
23
  @original.send(method, *args, &block)
24
24
  end
25
+
25
26
  end
26
27
  end
data/lib/savon/builder.rb CHANGED
@@ -1,59 +1,40 @@
1
1
  # frozen_string_literal: true
2
-
3
- require "savon/addressing"
4
2
  require "savon/header"
5
3
  require "savon/message"
6
- require "savon/effective_options"
7
4
  require "nokogiri"
8
5
  require "builder"
9
6
  require "gyoku"
10
7
 
11
8
  module Savon
12
- # Builds the SOAP request for an operation: the XML envelope, or
13
- # a multipart/related message when the request carries attachments
14
- # (SOAP with Attachments, https://www.w3.org/TR/SOAP-attachments).
15
- #
16
- # It owns the envelope structure, its namespace declarations, and the body,
17
- # and signs the document when a WSSE signature is present. Message-body
18
- # serialization is delegated to {Savon::Message}, the Header element to
19
- # {Savon::Header}, and Hash-to-XML conversion to Gyoku.
20
9
  class Builder
21
10
  attr_reader :multipart
22
11
 
23
12
  SCHEMA_TYPES = {
24
13
  "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
25
14
  "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance"
26
- }.freeze
15
+ }
27
16
 
28
17
  SOAP_NAMESPACE = {
29
18
  1 => "http://schemas.xmlsoap.org/soap/envelope/",
30
19
  2 => "http://www.w3.org/2003/05/soap-envelope"
31
- }.freeze
20
+ }
32
21
 
33
- # @deprecated Use {Savon::Addressing::NAMESPACE} instead. This alias will
34
- # be removed in Savon 3.0.
35
- WSA_NAMESPACE = Addressing::NAMESPACE
22
+ WSA_NAMESPACE = "http://www.w3.org/2005/08/addressing"
36
23
 
37
- # @param operation_name [Symbol] the SOAP operation being called
38
- # @param wsdl [Wasabi::Document] the parsed WSDL, or an empty document when
39
- # the client was configured without one
40
- # @param globals [Savon::GlobalOptions] client-level options
41
- # @param locals [Savon::LocalOptions] per-request options
42
24
  def initialize(operation_name, wsdl, globals, locals)
43
25
  @operation_name = operation_name
44
26
 
45
27
  @wsdl = wsdl
46
28
  @globals = globals
47
29
  @locals = locals
48
- @effective = EffectiveOptions.new(operation_name, wsdl, globals, locals)
49
- @signature = @effective.wsse_signature
30
+ @signature = @locals[:wsse_signature] || @globals[:wsse_signature]
50
31
 
51
32
  @types = convert_type_definitions_to_hash
52
33
  @used_namespaces = convert_type_namespaces_to_hash
53
34
  end
54
35
 
55
36
  def pretty
56
- Nokogiri.XML(to_s).to_xml(indent: 2)
37
+ Nokogiri.XML(to_s).to_xml(:indent => 2)
57
38
  end
58
39
 
59
40
  def build_document
@@ -80,57 +61,43 @@ module Savon
80
61
  end
81
62
  end
82
63
 
83
- # Returns the XML attributes of the envelope's Header element, provided
84
- # by the header's sections.
85
- #
86
- # @return [Hash{String => String}]
87
64
  def header_attributes
88
- header.attributes
65
+ @globals[:use_wsa_headers] ? { 'xmlns:wsa' => WSA_NAMESPACE } : {}
89
66
  end
90
67
 
91
68
  def body_attributes
92
69
  @body_attributes ||= @signature.nil? ? {} : @signature.body_attributes
93
70
  end
94
71
 
95
- # Returns the request body as a String. When the caller supplies a pre-built
96
- # envelope via the :xml local option it is used verbatim, but it must still
97
- # be wrapped in a multipart message when :attachments are present.
98
- # Otherwise the attachments are silently dropped.
99
72
  def to_s
100
- if @locals.include?(:xml)
101
- xml = @locals[:xml]
102
- @locals[:attachments] ? build_multipart_message(xml) : xml
103
- else
104
- build_document
105
- end
73
+ return @locals[:xml] if @locals.include? :xml
74
+ build_document
106
75
  end
107
76
 
108
77
  private
109
78
 
110
79
  def convert_type_definitions_to_hash
111
- @wsdl.type_definitions.each_with_object({}) do |(path, type), memo|
80
+ @wsdl.type_definitions.inject({}) do |memo, (path, type)|
112
81
  memo[path] = type
82
+ memo
113
83
  end
114
84
  end
115
85
 
116
86
  def convert_type_namespaces_to_hash
117
- @wsdl.type_namespaces.each_with_object({}) do |(path, uri), memo|
87
+ @wsdl.type_namespaces.inject({}) do |memo, (path, uri)|
118
88
  key, value = use_namespace(path, uri)
119
89
  memo[key] = value
90
+ memo
120
91
  end
121
92
  end
122
93
 
123
94
  def use_namespace(path, uri)
124
95
  @internal_namespace_count ||= 0
125
96
 
126
- unless (identifier = namespace_by_uri(uri))
127
- wsdl_identifier = @wsdl.document? ? @wsdl.parser.namespaces.key(uri) : nil
128
- # The prefix may already be taken by the target namespace or a user-supplied
129
- # :namespaces override - fall back to ins0, ins1... rather than overwriting it.
130
- wsdl_identifier = nil if wsdl_identifier && namespaces.key?("xmlns:#{wsdl_identifier}")
131
- identifier = wsdl_identifier || "ins#{@internal_namespace_count}"
97
+ unless identifier = namespace_by_uri(uri)
98
+ identifier = "ins#{@internal_namespace_count}"
132
99
  namespaces["xmlns:#{identifier}"] = uri
133
- @internal_namespace_count += 1 unless wsdl_identifier
100
+ @internal_namespace_count += 1
134
101
  end
135
102
 
136
103
  [path, identifier]
@@ -149,9 +116,21 @@ module Savon
149
116
  @globals[:namespace] || @wsdl.namespace
150
117
 
151
118
  # check env_namespace
152
- namespaces["xmlns#{env_namespace && env_namespace != '' ? ":#{env_namespace}" : ''}"] =
119
+ namespaces["xmlns#{env_namespace && env_namespace != "" ? ":#{env_namespace}" : ''}"] =
153
120
  SOAP_NAMESPACE[@globals[:soap_version]]
154
121
 
122
+ if @wsdl&.document
123
+ @wsdl.parser.namespaces.each do |identifier, path|
124
+ next if identifier == 'xmlns' # Do not include xmlns namespace as this causes issues for some servers (https://github.com/savonrb/savon/issues/986)
125
+
126
+ prefixed_identifier = "xmlns:#{identifier}"
127
+
128
+ next if namespaces.key?(prefixed_identifier)
129
+
130
+ namespaces[prefixed_identifier] = path
131
+ end
132
+ end
133
+
155
134
  namespaces
156
135
  end
157
136
  end
@@ -161,14 +140,13 @@ module Savon
161
140
  end
162
141
 
163
142
  def header
164
- @header ||= Header.new(@globals, @effective)
143
+ @header ||= Header.new(@globals, @locals)
165
144
  end
166
145
 
167
146
  def namespaced_message_tag
168
147
  tag_name = message_tag
169
- return [tag_name] if @wsdl.document? && @wsdl.soap_input(@operation_name.to_sym).is_a?(Hash)
170
-
171
- if namespace_identifier.nil?
148
+ return [tag_name] if @wsdl.document? and @wsdl.soap_input(@operation_name.to_sym).is_a?(Hash)
149
+ if namespace_identifier == nil
172
150
  [tag_name, message_attributes]
173
151
  elsif @used_namespaces[[tag_name.to_s]]
174
152
  [@used_namespaces[[tag_name.to_s]], tag_name, message_attributes]
@@ -186,7 +164,6 @@ module Savon
186
164
  message_tag = serialized_message_tag[1]
187
165
  @wsdl.soap_input(@operation_name.to_sym)[message_tag].each_pair do |message, type|
188
166
  break if @locals[:message].nil?
189
-
190
167
  message_locals = @locals[:message][StringUtils.snakecase(message).to_sym]
191
168
  message_content = Message.new(message_tag, namespace_identifier, @types, @used_namespaces, message_locals, :unqualified, @globals[:convert_request_keys_to], @globals[:unwrap]).to_s
192
169
  messages += "<#{message} xsi:type=\"#{type.join(':')}\">#{message_content}</#{message}>"
@@ -200,7 +177,7 @@ module Savon
200
177
  message_tag = wsdl_tag_name.keys.first if wsdl_tag_name.is_a?(Hash)
201
178
  message_tag ||= @locals[:message_tag]
202
179
  message_tag ||= wsdl_tag_name
203
- message_tag ||= Gyoku.xml_tag(@operation_name, key_converter: @globals[:convert_request_keys_to])
180
+ message_tag ||= Gyoku.xml_tag(@operation_name, :key_converter => @globals[:convert_request_keys_to])
204
181
 
205
182
  message_tag.to_sym
206
183
  end
@@ -210,7 +187,7 @@ module Savon
210
187
  end
211
188
 
212
189
  def body_message
213
- if @wsdl.document? && @wsdl.soap_input(@operation_name.to_sym).is_a?(Hash)
190
+ if @wsdl.document? and @wsdl.soap_input(@operation_name.to_sym).is_a?(Hash)
214
191
  serialized_messages
215
192
  else
216
193
  message.to_s
@@ -244,7 +221,7 @@ module Savon
244
221
 
245
222
  def builder
246
223
  builder = ::Builder::XmlMarkup.new
247
- builder.instruct!(:xml, encoding: @globals[:encoding])
224
+ builder.instruct!(:xml, :encoding => @globals[:encoding])
248
225
  builder
249
226
  end
250
227
 
@@ -277,7 +254,7 @@ module Savon
277
254
 
278
255
  # the mail.body.encoded algorithm reorders the parts, default order is [ "text/plain", "text/enriched", "text/html" ]
279
256
  # should redefine the sort order, because the soap request xml should be the first
280
- multipart_message.body.set_sort_order ["text/xml"]
257
+ multipart_message.body.set_sort_order [ "text/xml" ]
281
258
 
282
259
  multipart_message.body.encoded(multipart_message.content_transfer_encoding)
283
260
  end
@@ -292,10 +269,10 @@ module Savon
292
269
  end
293
270
  multipart_message.add_part xml_part
294
271
 
295
- # request.headers["Content-Type"] = "multipart/related; boundary=\"#{multipart_message.body.boundary}\"; type=\"text/xml\"; start=\"#{xml_part.content_id}\""
272
+ #request.headers["Content-Type"] = "multipart/related; boundary=\"#{multipart_message.body.boundary}\"; type=\"text/xml\"; start=\"#{xml_part.content_id}\""
296
273
  @multipart = {
297
274
  multipart_boundary: multipart_message.body.boundary,
298
- start: xml_part.content_id
275
+ start: xml_part.content_id,
299
276
  }
300
277
 
301
278
  multipart_message