savon 2.2.0 → 2.3.0

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.
@@ -15,17 +15,21 @@ module Savon
15
15
  return hash.to_s unless hash.kind_of? Hash
16
16
 
17
17
  hash.inject({}) do |newhash, (key, value)|
18
- translated_key = Gyoku.xml_tag(key, :key_converter => @key_converter).to_s
19
- newpath = path + [translated_key]
20
-
21
- if @used_namespaces[newpath]
22
- newhash.merge(
23
- "#{@used_namespaces[newpath]}:#{translated_key}" =>
24
- to_hash(value, @types[newpath] ? [@types[newpath]] : newpath)
25
- )
26
- else
27
- add_namespaces_to_values(value, path) if key == :order!
18
+ if key == :order!
19
+ add_namespaces_to_values(value, path)
28
20
  newhash.merge(key => value)
21
+ else
22
+ translated_key = Gyoku.xml_tag(key, :key_converter => @key_converter).to_s
23
+ newpath = path + [translated_key]
24
+
25
+ if @used_namespaces[newpath]
26
+ newhash.merge(
27
+ "#{@used_namespaces[newpath]}:#{translated_key}" =>
28
+ to_hash(value, @types[newpath] ? [@types[newpath]] : newpath)
29
+ )
30
+ else
31
+ newhash.merge(translated_key => value)
32
+ end
29
33
  end
30
34
  end
31
35
  end
@@ -37,6 +37,7 @@ module Savon
37
37
  def configure_auth
38
38
  @http_request.auth.basic(*@globals[:basic_auth]) if @globals.include? :basic_auth
39
39
  @http_request.auth.digest(*@globals[:digest_auth]) if @globals.include? :digest_auth
40
+ @http_request.auth.ntlm(*@globals[:ntlm]) if @globals.include? :ntlm
40
41
  end
41
42
 
42
43
  end
@@ -0,0 +1,48 @@
1
+ require "savon/log_message"
2
+
3
+ module Savon
4
+ class RequestLogger
5
+
6
+ def initialize(globals)
7
+ @globals = globals
8
+ end
9
+
10
+ def log(request, &http_request)
11
+ log_request(request) if log?
12
+ response = http_request.call
13
+ log_response(response) if log?
14
+
15
+ response
16
+ end
17
+
18
+ def logger
19
+ @globals[:logger]
20
+ end
21
+
22
+ def log?
23
+ @globals[:log]
24
+ end
25
+
26
+ private
27
+
28
+ def log_request(request)
29
+ logger.info "SOAP request: #{request.url}"
30
+ logger.info headers_to_log(request.headers)
31
+ logger.debug body_to_log(request.body)
32
+ end
33
+
34
+ def log_response(response)
35
+ logger.info "SOAP response (status #{response.code})"
36
+ logger.debug body_to_log(response.body)
37
+ end
38
+
39
+ def headers_to_log(headers)
40
+ headers.map { |key, value| "#{key}: #{value}" }.join(", ")
41
+ end
42
+
43
+ def body_to_log(body)
44
+ LogMessage.new(body, @globals[:filters], @globals[:pretty_print_xml]).to_s
45
+ end
46
+
47
+ end
48
+ end
@@ -10,15 +10,16 @@ module Savon
10
10
  @globals = globals
11
11
  @locals = locals
12
12
 
13
+ build_soap_and_http_errors!
13
14
  raise_soap_and_http_errors! if @globals[:raise_errors]
14
15
  end
15
16
 
16
- attr_reader :http, :globals, :locals
17
+ attr_reader :http, :globals, :locals, :soap_fault, :http_error
17
18
 
18
19
  def success?
19
20
  !soap_fault? && !http_error?
20
21
  end
21
- alias successful? success?
22
+ alias_method :successful?, :success?
22
23
 
23
24
  def soap_fault?
24
25
  SOAPFault.present? @http
@@ -29,15 +30,14 @@ module Savon
29
30
  end
30
31
 
31
32
  def header
32
- raise_invalid_response_error! unless hash.key? :envelope
33
- hash[:envelope][:header]
33
+ find('Header')
34
34
  end
35
35
 
36
36
  def body
37
- raise_invalid_response_error! unless hash.key? :envelope
38
- hash[:envelope][:body]
37
+ find('Body')
39
38
  end
40
- alias to_hash body
39
+
40
+ alias_method :to_hash, :body
41
41
 
42
42
  def to_array(*path)
43
43
  result = path.inject body do |memo, key|
@@ -49,30 +49,45 @@ module Savon
49
49
  end
50
50
 
51
51
  def hash
52
- @hash ||= nori.parse(to_xml)
52
+ @hash ||= nori.parse(xml)
53
53
  end
54
54
 
55
- def to_xml
55
+ def xml
56
56
  @http.body
57
57
  end
58
58
 
59
+ alias_method :to_xml, :xml
60
+ alias_method :to_s, :xml
61
+
59
62
  def doc
60
- @doc ||= Nokogiri.XML(to_xml)
63
+ @doc ||= Nokogiri.XML(xml)
61
64
  end
62
65
 
63
66
  def xpath(path, namespaces = nil)
64
67
  doc.xpath(path, namespaces || xml_namespaces)
65
68
  end
66
69
 
70
+ def find(*path)
71
+ envelope = nori.find(hash, 'Envelope')
72
+ raise_invalid_response_error! unless envelope
73
+
74
+ nori.find(envelope, *path)
75
+ end
76
+
67
77
  private
68
78
 
79
+ def build_soap_and_http_errors!
80
+ @soap_fault = SOAPFault.new(@http, nori) if soap_fault?
81
+ @http_error = HTTPError.new(@http) if http_error?
82
+ end
83
+
69
84
  def raise_soap_and_http_errors!
70
- raise SOAPFault.new(@http, nori) if soap_fault?
71
- raise HTTPError.new(@http) if http_error?
85
+ raise soap_fault if soap_fault?
86
+ raise http_error if http_error?
72
87
  end
73
88
 
74
89
  def raise_invalid_response_error!
75
- raise InvalidResponseError, "Unable to parse response body:\n" + to_xml.inspect
90
+ raise InvalidResponseError, "Unable to parse response body:\n" + xml.inspect
76
91
  end
77
92
 
78
93
  def xml_namespaces
@@ -1,5 +1,5 @@
1
1
  module Savon
2
2
 
3
- VERSION = "2.2.0"
3
+ VERSION = "2.3.0"
4
4
 
5
5
  end
@@ -14,22 +14,23 @@ Gem::Specification.new do |s|
14
14
  s.description = s.summary
15
15
 
16
16
  s.rubyforge_project = s.name
17
+ s.license = 'MIT'
17
18
 
18
- s.add_dependency "nori", "~> 2.1.0"
19
- s.add_dependency "httpi", "~> 2.0.2"
20
- s.add_dependency "wasabi", "~> 3.1.0"
19
+ s.add_dependency "nori", "~> 2.3.0"
20
+ s.add_dependency "httpi", "~> 2.1.0"
21
+ s.add_dependency "wasabi", "~> 3.2.0"
21
22
  s.add_dependency "akami", "~> 1.2.0"
22
- s.add_dependency "gyoku", "~> 1.0.0"
23
+ s.add_dependency "gyoku", "~> 1.1.0"
23
24
 
24
25
  s.add_dependency "builder", ">= 2.1.2"
25
- s.add_dependency "nokogiri", ">= 1.4.0"
26
+ s.add_dependency "nokogiri", ">= 1.4.0", "< 1.6"
26
27
 
27
28
  s.add_development_dependency "rack"
28
29
  s.add_development_dependency "puma", "2.0.0.b4"
29
30
 
30
- s.add_development_dependency "rake", "~> 0.9"
31
- s.add_development_dependency "rspec", "~> 2.10"
32
- s.add_development_dependency "mocha", "~> 0.11"
31
+ s.add_development_dependency "rake", "~> 10.1"
32
+ s.add_development_dependency "rspec", "~> 2.14"
33
+ s.add_development_dependency "mocha", "~> 0.14"
33
34
  s.add_development_dependency "json", "~> 1.7"
34
35
 
35
36
  ignores = File.readlines(".gitignore").grep(/\S+/).map(&:chomp)
@@ -0,0 +1,176 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <wsdl:definitions targetNamespace="urn:ec.europa.eu:taxud:vies:services:checkVat" xmlns:tns1="urn:ec.europa.eu:taxud:vies:services:checkVat:types" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:impl="urn:ec.europa.eu:taxud:vies:services:checkVat" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
3
+ <xsd:documentation>
4
+ Specific disclaimer for this service ----------------------------------------- The
5
+ objective of this Internet site is to allow persons involved in the intra-Community supply of
6
+ goods or of services to obtain confirmation of the validity of the VAT identification number of
7
+ any specified person, in accordance to article 27 of Council Regulation (EC) No. 1798/2003 of 7
8
+ October 2003. Any other use and any extraction and use of the data which is not in conformity
9
+ with the objective of this site is strictly forbidden. Any retransmission of the contents of
10
+ this site, whether for a commercial purpose or otherwise, as well as any more general use other
11
+ than as far as is necessary to support the activity of a legitimate user (for example: to draw
12
+ up their own invoices) is expressly forbidden. In addition, any copying or reproduction of the
13
+ contents of this site is strictly forbidden. The European Commission maintains this website to
14
+ enhance the access by taxable persons making intra-Community supplies to verification of their
15
+ customers VAT identification numbers. Our goal is to supply instantaneous and accurate
16
+ information. However the Commission accepts no responsibility or liability whatsoever with
17
+ regard to the information obtained using this site. This information: - is obtained from Member
18
+ States databases over which the Commission services have no control and for which the Commission
19
+ assumes no responsibility; it is the responsibility of the Member States to keep their databases
20
+ complete, accurate and up to date; - is not professional or legal advice (if you need specific
21
+ advice, you should always consult a suitably qualified professional); - does not in itself give
22
+ a right to exempt intra-Community supplies from Value Added Tax; - does not change any
23
+ obligations imposed on taxable persons in relation to intra-Community supplies. It is our goal
24
+ to minimise disruption caused by technical errors. However some data or information on our site
25
+ may have been created or structured in files or formats which are not error-free and we cannot
26
+ guarantee that our service will not be interrupted or otherwise affected by such problems. The
27
+ Commission accepts no responsibility with regard to such problems incurred as a result of using
28
+ this site or any linked external sites. This disclaimer is not intended to limit the liability
29
+ of the Commission in contravention of any requirements laid down in applicable national law nor
30
+ to exclude its liability for matters which may not be excluded under that law. Usage: The
31
+ countryCode input parameter must follow the pattern [A-Z]{2} The vatNumber input parameter must
32
+ follow the [0-9A-Za-z\+\*\.]{2,12} In case of problem, the returned FaultString can take the
33
+ following specific values: - INVALID_INPUT: The provided CountryCode is invalid or the VAT
34
+ number is empty; - SERVICE_UNAVAILABLE: The SOAP service is unavailable, try again later; -
35
+ MS_UNAVAILABLE: The Member State service is unavailable, try again later or with another Member
36
+ State; - TIMEOUT: The Member State service could not be reach in time, try again later or with
37
+ another Member State; - SERVER_BUSY: The service can't process your request. Try again latter.
38
+ </xsd:documentation>
39
+
40
+ <wsdl:types>
41
+ <xsd:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="urn:ec.europa.eu:taxud:vies:services:checkVat:types" xmlns="urn:ec.europa.eu:taxud:vies:services:checkVat:types">
42
+ <xsd:element name="checkVat">
43
+ <xsd:complexType>
44
+ <xsd:sequence>
45
+ <xsd:element name="countryCode" type="xsd:string"/>
46
+ <xsd:element name="vatNumber" type="xsd:string"/>
47
+ </xsd:sequence>
48
+ </xsd:complexType>
49
+ </xsd:element>
50
+ <xsd:element name="checkVatResponse">
51
+ <xsd:complexType>
52
+ <xsd:sequence>
53
+ <xsd:element name="countryCode" type="xsd:string"/>
54
+ <xsd:element name="vatNumber" type="xsd:string"/>
55
+ <xsd:element name="requestDate" type="xsd:date"/>
56
+ <xsd:element name="valid" type="xsd:boolean"/>
57
+ <xsd:element maxOccurs="1" minOccurs="0" name="name" nillable="true" type="xsd:string"/>
58
+ <xsd:element maxOccurs="1" minOccurs="0" name="address" nillable="true" type="xsd:string"/>
59
+ </xsd:sequence>
60
+ </xsd:complexType>
61
+ </xsd:element>
62
+ <xsd:element name="checkVatApprox">
63
+ <xsd:complexType>
64
+ <xsd:sequence>
65
+ <xsd:element name="countryCode" type="xsd:string"/>
66
+ <xsd:element name="vatNumber" type="xsd:string"/>
67
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderName" type="xsd:string"/>
68
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderCompanyType" type="tns1:companyTypeCode"/>
69
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderStreet" type="xsd:string"/>
70
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderPostcode" type="xsd:string"/>
71
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderCity" type="xsd:string"/>
72
+ <xsd:element maxOccurs="1" minOccurs="0" name="requesterCountryCode" type="xsd:string"/>
73
+ <xsd:element maxOccurs="1" minOccurs="0" name="requesterVatNumber" type="xsd:string"/>
74
+ </xsd:sequence>
75
+ </xsd:complexType>
76
+ </xsd:element>
77
+ <xsd:element name="checkVatApproxResponse">
78
+ <xsd:complexType>
79
+ <xsd:sequence>
80
+ <xsd:element name="countryCode" type="xsd:string"/>
81
+ <xsd:element name="vatNumber" type="xsd:string"/>
82
+ <xsd:element name="requestDate" type="xsd:date"/>
83
+ <xsd:element name="valid" type="xsd:boolean"/>
84
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderName" nillable="true" type="xsd:string"/>
85
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderCompanyType" nillable="true" type="tns1:companyTypeCode"/>
86
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderAddress" type="xsd:string"/>
87
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderStreet" type="xsd:string"/>
88
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderPostcode" type="xsd:string"/>
89
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderCity" type="xsd:string"/>
90
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderNameMatch" type="tns1:matchCode"/>
91
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderCompanyTypeMatch" type="tns1:matchCode"/>
92
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderStreetMatch" type="tns1:matchCode"/>
93
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderPostcodeMatch" type="tns1:matchCode"/>
94
+ <xsd:element maxOccurs="1" minOccurs="0" name="traderCityMatch" type="tns1:matchCode"/>
95
+ <xsd:element name="requestIdentifier" type="xsd:string"/>
96
+ </xsd:sequence>
97
+ </xsd:complexType>
98
+ </xsd:element>
99
+ <xsd:simpleType name="companyTypeCode">
100
+ <xsd:restriction base="xsd:string">
101
+ <xsd:pattern value="[A-Z]{2}\-[1-9][0-9]?"/>
102
+ </xsd:restriction>
103
+ </xsd:simpleType>
104
+ <xsd:simpleType name="matchCode">
105
+ <xsd:restriction base="xsd:string">
106
+ <xsd:enumeration value="1">
107
+ <xsd:annotation>
108
+ <xsd:documentation>VALID</xsd:documentation>
109
+ </xsd:annotation>
110
+ </xsd:enumeration>
111
+ <xsd:enumeration value="2">
112
+ <xsd:annotation>
113
+ <xsd:documentation>INVALID</xsd:documentation>
114
+ </xsd:annotation>
115
+ </xsd:enumeration>
116
+ </xsd:restriction>
117
+ </xsd:simpleType>
118
+ </xsd:schema>
119
+ </wsdl:types>
120
+ <wsdl:message name="checkVatRequest">
121
+ <wsdl:part name="parameters" element="tns1:checkVat">
122
+ </wsdl:part>
123
+ </wsdl:message>
124
+ <wsdl:message name="checkVatApproxResponse">
125
+ <wsdl:part name="parameters" element="tns1:checkVatApproxResponse">
126
+ </wsdl:part>
127
+ </wsdl:message>
128
+ <wsdl:message name="checkVatApproxRequest">
129
+ <wsdl:part name="parameters" element="tns1:checkVatApprox">
130
+ </wsdl:part>
131
+ </wsdl:message>
132
+ <wsdl:message name="checkVatResponse">
133
+ <wsdl:part name="parameters" element="tns1:checkVatResponse">
134
+ </wsdl:part>
135
+ </wsdl:message>
136
+ <wsdl:portType name="checkVatPortType">
137
+ <wsdl:operation name="checkVat">
138
+ <wsdl:input name="checkVatRequest" message="impl:checkVatRequest">
139
+ </wsdl:input>
140
+ <wsdl:output name="checkVatResponse" message="impl:checkVatResponse">
141
+ </wsdl:output>
142
+ </wsdl:operation>
143
+ <wsdl:operation name="checkVatApprox">
144
+ <wsdl:input name="checkVatApproxRequest" message="impl:checkVatApproxRequest">
145
+ </wsdl:input>
146
+ <wsdl:output name="checkVatApproxResponse" message="impl:checkVatApproxResponse">
147
+ </wsdl:output>
148
+ </wsdl:operation>
149
+ </wsdl:portType>
150
+ <wsdl:binding name="checkVatBinding" type="impl:checkVatPortType">
151
+ <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
152
+ <wsdl:operation name="checkVat">
153
+ <wsdlsoap:operation soapAction=""/>
154
+ <wsdl:input name="checkVatRequest">
155
+ <wsdlsoap:body use="literal"/>
156
+ </wsdl:input>
157
+ <wsdl:output name="checkVatResponse">
158
+ <wsdlsoap:body use="literal"/>
159
+ </wsdl:output>
160
+ </wsdl:operation>
161
+ <wsdl:operation name="checkVatApprox">
162
+ <wsdlsoap:operation soapAction=""/>
163
+ <wsdl:input name="checkVatApproxRequest">
164
+ <wsdlsoap:body use="literal"/>
165
+ </wsdl:input>
166
+ <wsdl:output name="checkVatApproxResponse">
167
+ <wsdlsoap:body use="literal"/>
168
+ </wsdl:output>
169
+ </wsdl:operation>
170
+ </wsdl:binding>
171
+ <wsdl:service name="checkVatService">
172
+ <wsdl:port name="checkVatPort" binding="impl:checkVatBinding">
173
+ <wsdlsoap:address location="http://ec.europa.eu/taxation_customs/vies/services/checkVatService"/>
174
+ </wsdl:port>
175
+ </wsdl:service>
176
+ </wsdl:definitions>
@@ -81,7 +81,6 @@ describe Savon::Builder do
81
81
 
82
82
  expect(builder.to_s).to include("<tns:username>luke</tns:username>")
83
83
  end
84
-
85
84
  end
86
85
 
87
86
  end
@@ -27,6 +27,11 @@ describe Savon do
27
27
  expect(message_tag).to eq(['http://www.betfair.com/publicapi/v5/BFExchangeService/', 'getBet'])
28
28
  end
29
29
 
30
+ it 'knows the message tag for :vies' do
31
+ message_tag = message_tag_for(:vies, :check_vat)
32
+ expect(message_tag).to eq(['urn:ec.europa.eu:taxud:vies:services:checkVat:types', 'checkVat'])
33
+ end
34
+
30
35
  it 'knows the message tag for :wasmuth' do
31
36
  message_tag = message_tag_for(:wasmuth, :get_st_tables)
32
37
  expect(message_tag).to eq(['http://ws.online.msw/', 'getStTables'])
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+ require "integration/support/server"
3
+
4
+ describe Savon::Message do
5
+
6
+ before do
7
+ @server = IntegrationServer.run
8
+ end
9
+
10
+ after do
11
+ @server.stop
12
+ end
13
+
14
+ context "with a qualified message" do
15
+ it "converts request Hash keys for which there is not namespace" do
16
+ client = Savon.client(
17
+ :endpoint => @server.url(:repeat),
18
+ :namespace => 'http://example.com',
19
+ :log => false,
20
+
21
+ :element_form_default => :qualified,
22
+ :convert_request_keys_to => :camelcase,
23
+
24
+ :convert_response_tags_to => nil
25
+ )
26
+
27
+ message = {
28
+ :email_count => 3,
29
+ :user_name => 'josh',
30
+ :order! => [:user_name, :email_count]
31
+ }
32
+
33
+ response = client.call(:something, :message => message)
34
+ body = response.hash['Envelope']['Body']
35
+
36
+ expect(response.xml).to include('<wsdl:UserName>josh</wsdl:UserName><wsdl:EmailCount>3</wsdl:EmailCount>')
37
+ end
38
+ end
39
+
40
+ end