savon 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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