savon 0.9.7 → 0.9.8

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,5 +1,4 @@
1
1
  # https://github.com/travis-ci/travis-ci/wiki/.travis.yml-options
2
- bundler_args: --without developer_happiness
3
2
  script: "bundle exec rake"
4
3
  rvm:
5
4
  - 1.8.7
@@ -9,3 +8,5 @@ rvm:
9
8
  - rbx
10
9
  - rbx-2.0
11
10
  - jruby
11
+ notifications:
12
+ irc: "irc.freenode.org#savon"
data/.yardopts CHANGED
@@ -1,2 +1,5 @@
1
+ --markup markdown
2
+ --markup-provider redcarpet
1
3
  -
2
- CHANGELOG.rdoc
4
+ CHANGELOG.md
5
+ LICENSE
@@ -1,3 +1,37 @@
1
+ ## 0.9.8 (2012-02-15)
2
+
3
+ * Feature: Savon now ships with [Savon::Model](http://rubygems.org/gems/savon_model).
4
+ Savon::Model is a lightweight DSL to be used inside your domain models. It's been refactored
5
+ and is now [even more useful](http://savonrb.com/#how_to_date_a_model) than before.
6
+
7
+ * Feature: Merged [pull request 230](https://github.com/rubiii/savon/pull/230) to allow filtering values
8
+ in logged SOAP request XML messages.
9
+
10
+ ``` ruby
11
+ Savon.configure do |config|
12
+ config.log_filter = ["password"]
13
+ end
14
+ ```
15
+
16
+ * Feature: Added an option to change the default encoding of the XML directive tag (defaults to UTF-8)
17
+ to fix [issue 234](https://github.com/rubiii/savon/issues/234).
18
+
19
+ ``` ruby
20
+ client.request(:find_user) do
21
+ soap.encoding = "UTF-16"
22
+ soap.body = { :id => 1 }
23
+ end
24
+ ```
25
+
26
+ * Improvement: Merged [pull request 231](https://github.com/rubiii/savon/pull/231) to gracefully handle
27
+ invalid response bodies by throwing a `Savon::SOAP::InvalidResponseError`.
28
+
29
+ * Fix: [issue 237](https://github.com/rubiii/savon/issues/237) - Set the Content-Type and Content-Length
30
+ headers for every request.
31
+
32
+ * Fix: [pull request 250](https://github.com/rubiii/savon/pull/250) - The Content-Length header should
33
+ be the size in bytes.
34
+
1
35
  ## 0.9.7 (2011-08-25)
2
36
 
3
37
  * Feature: Merged [pull request 210](https://github.com/rubiii/savon/pull/210) by
data/Gemfile CHANGED
@@ -2,8 +2,3 @@ source :rubygems
2
2
  gemspec
3
3
 
4
4
  gem "httpclient", "~> 2.1.5"
5
-
6
- # excluded from travis
7
- group :developer_happiness do
8
- gem "autotest"
9
- end
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
- Savon [![Build Status](http://travis-ci.org/rubiii/savon.png)](http://travis-ci.org/rubiii/savon)
1
+ Savon [![Build Status](https://secure.travis-ci.org/rubiii/savon.png)](http://travis-ci.org/rubiii/savon)
2
2
  =====
3
3
 
4
4
  Heavy metal Ruby SOAP client
5
5
 
6
6
  [Documentation](http://savonrb.com) | [RDoc](http://rubydoc.info/gems/savon) |
7
- [Mailing list](http://groups.google.com/group/savon-soap) | [Twitter](http://twitter.com/savonrb)
7
+ [Mailing list](https://groups.google.com/forum/#!forum/savonrb) | [Twitter](http://twitter.com/savonrb)
8
8
 
9
9
  Installation
10
10
  ------------
@@ -15,26 +15,28 @@ Savon is available through [Rubygems](http://rubygems.org/gems/savon) and can be
15
15
  $ gem install savon
16
16
  ```
17
17
 
18
- Basic workflow
19
- --------------
18
+ Introduction
19
+ ------------
20
20
 
21
21
  ``` ruby
22
- # Setting up a Savon::Client representing a SOAP service.
23
- client = Savon::Client.new "http://service.example.com?wsdl"
22
+ require "savon"
23
+
24
+ # create a client for your SOAP service
25
+ client = Savon::Client.new("http://service.example.com?wsdl")
24
26
 
25
27
  client.wsdl.soap_actions
26
28
  # => [:create_user, :get_user, :get_all_users]
27
29
 
28
- # Executing a SOAP request to call a "getUser" action.
29
- response = client.request :get_user do
30
+ # execute a SOAP request to call the "getUser" action
31
+ response = client.request(:get_user) do
30
32
  soap.body = { :id => 1 }
31
33
  end
32
34
 
33
- response.to_hash
35
+ response.body
34
36
  # => { :get_user_response => { :first_name => "The", :last_name => "Hoff" } }
35
37
  ```
36
38
 
37
- Ready for more?
38
- ---------------
39
+ Documentation
40
+ -------------
39
41
 
40
- [Go ahead and read the official documentation](http://savonrb.com).
42
+ Continue reading at [savonrb.com](http://savonrb.com)
data/Rakefile CHANGED
@@ -1,11 +1,7 @@
1
- require "bundler"
2
- Bundler::GemHelper.install_tasks
3
-
1
+ require "bundler/gem_tasks"
4
2
  require "rspec/core/rake_task"
5
3
 
6
- RSpec::Core::RakeTask.new do |t|
7
- t.rspec_opts = %w(-c)
8
- end
4
+ RSpec::Core::RakeTask.new
9
5
 
10
6
  task :default => :spec
11
7
  task :test => :spec
@@ -1,12 +1,13 @@
1
1
  require "savon/version"
2
- require "savon/global"
2
+ require "savon/config"
3
3
  require "savon/client"
4
+ require "savon/model"
4
5
 
5
6
  module Savon
6
- extend Global
7
+ extend Config
7
8
 
8
9
  # Yields this module to a given +block+. Please refer to the
9
- # <tt>Savon::Global</tt> module for configuration options.
10
+ # <tt>Savon::Config</tt> module for configuration options.
10
11
  def self.configure
11
12
  yield self if block_given?
12
13
  end
@@ -0,0 +1,103 @@
1
+ require "logger"
2
+ require "savon/soap"
3
+ require "savon/hooks/group"
4
+
5
+ module Savon
6
+ module Config
7
+
8
+ # Sets whether to log HTTP requests.
9
+ attr_writer :log
10
+
11
+ # Returns whether to log HTTP requests. Defaults to +true+.
12
+ def log?
13
+ @log != false
14
+ end
15
+
16
+ # Sets the logger to use.
17
+ attr_writer :logger
18
+
19
+ # Returns the logger. Defaults to an instance of +Logger+ writing to STDOUT.
20
+ def logger
21
+ @logger ||= ::Logger.new STDOUT
22
+ end
23
+
24
+ # Sets the log level.
25
+ attr_writer :log_level
26
+
27
+ # Returns the log level. Defaults to :debug.
28
+ def log_level
29
+ @log_level ||= :debug
30
+ end
31
+
32
+ # Logs a given +message+. Optionally filtered if +xml+ is truthy.
33
+ def log(message, xml = false)
34
+ return unless log?
35
+ message = filter_xml(message) if xml && !log_filter.empty?
36
+ logger.send log_level, message
37
+ end
38
+
39
+ # Returns the log filter. Defaults to an empty Array.
40
+ def log_filter
41
+ @log_filter ||= []
42
+ end
43
+
44
+ # Sets the log filter. Expects an Array.
45
+ attr_writer :log_filter
46
+
47
+ # Filters the given +xml+ based on log filter.
48
+ def filter_xml(xml)
49
+ doc = Nokogiri::XML(xml)
50
+ return xml unless doc.errors.empty?
51
+
52
+ log_filter.each do |filter|
53
+ doc.xpath("//*[local-name()='#{filter}']").map { |node| node.content = "***FILTERED***" }
54
+ end
55
+
56
+ doc.root.to_s
57
+ end
58
+
59
+ # Sets whether to raise HTTP errors and SOAP faults.
60
+ attr_writer :raise_errors
61
+
62
+ # Returns whether to raise errors. Defaults to +true+.
63
+ def raise_errors?
64
+ @raise_errors != false
65
+ end
66
+
67
+ # Sets the global SOAP version.
68
+ def soap_version=(version)
69
+ raise ArgumentError, "Invalid SOAP version: #{version}" if version && !SOAP::Versions.include?(version)
70
+ @version = version
71
+ end
72
+
73
+ # Returns SOAP version. Defaults to +DefaultVersion+.
74
+ def soap_version
75
+ @version ||= SOAP::DefaultVersion
76
+ end
77
+
78
+ # Accessor for the global env_namespace.
79
+ attr_accessor :env_namespace
80
+
81
+ # Accessor for the global soap_header.
82
+ attr_accessor :soap_header
83
+
84
+ # Returns the hooks.
85
+ def hooks
86
+ @hooks ||= Hooks::Group.new
87
+ end
88
+
89
+ # Reset to default configuration.
90
+ def reset_config!
91
+ self.log = nil
92
+ self.logger = nil
93
+ self.log_level = nil
94
+ self.log_filter = nil
95
+ self.raise_errors = nil
96
+ self.soap_version = nil
97
+ self.env_namespace = nil
98
+ self.soap_header = nil
99
+ end
100
+
101
+ end
102
+ end
103
+
@@ -0,0 +1,46 @@
1
+ require "savon/hooks/hook"
2
+
3
+ module Savon
4
+ module Hooks
5
+
6
+ # = Savon::Hooks::Group
7
+ #
8
+ # Manages a list of hooks.
9
+ class Group
10
+
11
+ # Accepts an Array of +hooks+ to start with.
12
+ def initialize(hooks = nil)
13
+ self.hooks = hooks
14
+ end
15
+
16
+ attr_writer :hooks
17
+
18
+ def hooks
19
+ @hooks ||= []
20
+ end
21
+
22
+ # Adds a new hook.
23
+ def define(id, hook, &block)
24
+ hooks << Hook.new(id, hook, &block)
25
+ end
26
+
27
+ # Removes hooks matching the given +ids+.
28
+ def reject!(*ids)
29
+ ids = ids.flatten
30
+ hooks.reject! { |hook| ids.include? hook.id }
31
+ end
32
+
33
+ # Returns a new group for a given +hook+.
34
+ def select(hook)
35
+ Group.new hooks.select { |h| h.hook == hook }
36
+ end
37
+
38
+ # Calls the hooks with the given +args+ and returns the
39
+ # value of the last hooks.
40
+ def call(*args)
41
+ hooks.inject(nil) { |memo, hook| hook.call(*args) }
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,36 @@
1
+ module Savon
2
+ module Hooks
3
+
4
+ # = Savon::Hooks::Hook
5
+ #
6
+ # A hook used somewhere in the system.
7
+ class Hook
8
+
9
+ HOOKS = [
10
+
11
+ # Replaces the POST request executed to call a service.
12
+ # See: Savon::SOAP::Request#response
13
+ #
14
+ # Receives the <tt>Savon::SOAP::Request</tt> and is expected to return an <tt>HTTPI::Response</tt>.
15
+ # It can change the request and return something falsy to still execute the POST request.
16
+ :soap_request
17
+
18
+ ]
19
+
20
+ # Expects an +id+, the name of the +hook+ to use and a +block+ to be called.
21
+ def initialize(id, hook, &block)
22
+ self.id = id
23
+ self.hook = hook
24
+ self.block = block
25
+ end
26
+
27
+ attr_accessor :id, :hook, :block
28
+
29
+ # Calls the +block+ with the given +args+.
30
+ def call(*args)
31
+ block.call(*args)
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,103 @@
1
+ module Savon
2
+
3
+ # = Savon::Model
4
+ #
5
+ # Model for SOAP service oriented applications.
6
+ module Model
7
+
8
+ def self.extended(base)
9
+ base.setup
10
+ end
11
+
12
+ def setup
13
+ class_action_module
14
+ instance_action_module
15
+ end
16
+
17
+ # Accepts one or more SOAP actions and generates both class and instance methods named
18
+ # after the given actions. Each generated method accepts an optional SOAP body Hash and
19
+ # a block to be passed to <tt>Savon::Client#request</tt> and executes a SOAP request.
20
+ def actions(*actions)
21
+ actions.each do |action|
22
+ define_class_action(action)
23
+ define_instance_action(action)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # Defines a class-level SOAP action method.
30
+ def define_class_action(action)
31
+ class_action_module.module_eval %{
32
+ def #{action.to_s.snakecase}(body = nil, &block)
33
+ response = client.request :wsdl, #{action.inspect}, :body => body, &block
34
+ Savon.hooks.select(:model_soap_response).call(response) || response
35
+ end
36
+ }
37
+ end
38
+
39
+ # Defines an instance-level SOAP action method.
40
+ def define_instance_action(action)
41
+ instance_action_module.module_eval %{
42
+ def #{action.to_s.snakecase}(body = nil, &block)
43
+ self.class.#{action.to_s.snakecase} body, &block
44
+ end
45
+ }
46
+ end
47
+
48
+ # Class methods.
49
+ def class_action_module
50
+ @class_action_module ||= Module.new do
51
+
52
+ # Returns the memoized <tt>Savon::Client</tt>.
53
+ def client(&block)
54
+ @client ||= Savon::Client.new(&block)
55
+ end
56
+
57
+ # Sets the SOAP endpoint to the given +uri+.
58
+ def endpoint(uri)
59
+ client.wsdl.endpoint = uri
60
+ end
61
+
62
+ # Sets the target namespace.
63
+ def namespace(uri)
64
+ client.wsdl.namespace = uri
65
+ end
66
+
67
+ # Sets the WSDL document to the given +uri+.
68
+ def document(uri)
69
+ client.wsdl.document = uri
70
+ end
71
+
72
+ # Sets the HTTP headers.
73
+ def headers(headers)
74
+ client.http.headers = headers
75
+ end
76
+
77
+ # Sets basic auth +login+ and +password+.
78
+ def basic_auth(login, password)
79
+ client.http.auth.basic(login, password)
80
+ end
81
+
82
+ # Sets WSSE auth credentials.
83
+ def wsse_auth(*args)
84
+ client.wsse.credentials(*args)
85
+ end
86
+
87
+ end.tap { |mod| extend(mod) }
88
+ end
89
+
90
+ # Instance methods.
91
+ def instance_action_module
92
+ @instance_action_module ||= Module.new do
93
+
94
+ # Returns the <tt>Savon::Client</tt> from the class instance.
95
+ def client(&block)
96
+ self.class.client(&block)
97
+ end
98
+
99
+ end.tap { |mod| include(mod) }
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,11 @@
1
+ require "savon/error"
2
+
3
+ module Savon
4
+ module SOAP
5
+ # = Savon::SOAP::InvalidResponseError
6
+ #
7
+ # Represents an error when the response was not a valid SOAP envelope.
8
+ class InvalidResponseError < Error
9
+ end
10
+ end
11
+ end