ruby2soap 0.0.1

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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ODAzMDk5Nzc5NmQ0NDk4YzhhYWFjYjMxY2VjNDc3MTk0NGY2ODgzOQ==
5
+ data.tar.gz: !binary |-
6
+ MzRlMDcwYWI3YzdiNDQwMmE0ZDA2Yzg3MTFjZjUxNzQ2MDMyZjAxYw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YzM5YmU1NWRmYmRjMGRlNzlkODA3ZjRhODVmOGIyOGUxZWMyNzVhYzc0ZDI2
10
+ Yjg4NmM4OTFhYThlOTBmZmI1ZmQ1ZjUxMGJlZGQ4NzM5MzRiZmJmZWVkYjJi
11
+ N2VmMDNiNDM5NGI1NmRhMzBmZDBmZGE1Y2NiYTAwYzEwNzc5NjY=
12
+ data.tar.gz: !binary |-
13
+ NjBiMmYxYmJhNzIzZDgxNDNmYzBmNDIzOTI3OGE3MDIwOTQyMjI1ZmU5OTRm
14
+ Y2I4MmZjZDgxYzhjN2I3ZTQ5YThiM2M2NDdkNzhkMmNmYTQ1NWZjZDFlNzhj
15
+ MjgwMGRiZTg5Y2RiYmVkMGIzMjM1ODRhMDk4NjI3NmM4YjYwZTM=
data/lib/ruby2soap.rb ADDED
@@ -0,0 +1,100 @@
1
+ require 'net/http'
2
+ require 'xmlsimple'
3
+ require_relative 'wsdl\wsdl'
4
+ include Wsdl
5
+ #require 'soap/soap'
6
+ #include Soap
7
+ #include WebRequestHandler
8
+ #require_relative 'wsdl.rb'
9
+ #require_relative 'wsdl_parser.rb'
10
+ #require_relative 'soap.rb'
11
+ #include WsdlParser
12
+ #include Soap
13
+
14
+ #Dir["lib/*.rb"].each {|file|
15
+ # require file
16
+ # #require_relative file# if file != 'wcf_handler'
17
+ # #include file.gsub('.rb','')
18
+ #}
19
+
20
+ # Handle the requests to the service
21
+ class Ruby2Soap
22
+ # C'tor.
23
+ # Parse the wsdl and create a method to each WCF/WebService method
24
+ # Params:
25
+ # +service_url+:: the url of your service
26
+ # +save_cookeis+:: should save cookies of the result
27
+ def initialize(service_url,save_cookeis = true)
28
+ HTTPI.log = false
29
+ @cookies = []
30
+ @save_cookeis = save_cookeis
31
+
32
+ @uri = URI("#{service_url}")
33
+
34
+ wsdl = WsdlParser.parse(service_url)
35
+ @service_address = wsdl.location_address
36
+
37
+ wsdl.actions.each do |action|
38
+ define_wcf_action(action)
39
+ end
40
+
41
+ # maybe create class for each service and the function will be there
42
+ end
43
+
44
+ # Return the the current cookie set
45
+ def cookies
46
+ @cookies
47
+ end
48
+
49
+ private
50
+ # Define a method to the +Ruby2Soap+ object base on the method from the WSDL
51
+ # Params:
52
+ # +action+:: +SoapAction+ that have all the info about the method from the WSDL
53
+ def define_wcf_action(action)
54
+ self.class.send(:define_method ,action.name) do |data=nil,*args|
55
+ body = build_body(action, data)
56
+
57
+ res = send_wcf_action(action.soap_action,body,*args)
58
+ (@cookies << res.headers["Set-Cookie"]) if @save_cookeis
59
+
60
+ result = get_wcf_response(res,action.name)
61
+ res.singleton_class.send(:define_method,:result) do
62
+ result
63
+ end
64
+
65
+ #if(res.code == '401') # not autorized
66
+ # (raise "Please use ntlm") if res['WWW-Authenticate'].include?('NTLM')
67
+ #end
68
+
69
+ res
70
+ end
71
+
72
+ #create new method that takes the data and user and password and user ntlm
73
+ end
74
+
75
+ # Call to wcf method
76
+ # Params:
77
+ # +soap_action+:: the value of the SOAPAction header
78
+ # +body+:: the body of the HTTP request
79
+ # +args+:: metadata that indicate wich autountication to use
80
+ def send_wcf_action(soap_action,body,*args)
81
+ #req = Net::HTTP::Post.new(@uri.path)
82
+ #req = Net::HTTP::Post.new(@service_address)
83
+
84
+ #req["SOAPAction"] = soap_action
85
+ #req["Content-Type"] = "text/xml; charset=utf-8"
86
+ #req["Cookie"] = @cookies.join(',') unless @cookies.empty?
87
+ #req.body = body
88
+
89
+ yield(req) if block_given?
90
+
91
+ #get_web_response(req,@uri,*args)
92
+ # "Cookie" => (@cookies.join(',') unless @cookies.empty?)
93
+ cookies = @cookies.empty? ? "" : @cookies.join(',')
94
+ send_message_to_wcf(@service_address,
95
+ {"SOAPAction" => soap_action,
96
+ "Content-Type" => "text/xml; charset=utf-8",
97
+ "Cookie" => cookies},
98
+ body, *args)
99
+ end
100
+ end
data/lib/soap/soap.rb ADDED
@@ -0,0 +1,88 @@
1
+ require_relative './soap_action'
2
+ require_relative './soap_parameter'
3
+ require 'xmlsimple'
4
+
5
+ module Soap
6
+ # Covert the data to hash
7
+ # Params:
8
+ # +object+:: the object to covert to hash
9
+ def data_to_arr(object)
10
+ return '' if object.nil?
11
+ return [object] unless object.is_a? Hash
12
+
13
+ params = {}
14
+ object.each do |key,value|
15
+ params["#{@name_space}:#{key}"] = data_to_arr(value)
16
+ end
17
+
18
+ params
19
+ end
20
+
21
+ # Build the body that need to be send to the service when calling the soap action and return the result
22
+ # Params :
23
+ # +action+:: +SoapAction+ object that keep all the data about the soap action
24
+ # +data+:: the user data that he want to send to the server
25
+ def build_body(action , data)
26
+ @name_space = 'a'
27
+ body = {
28
+ 'soap:Envelope' => {
29
+ 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/',
30
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
31
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
32
+ 'soap:Body' => {
33
+ "#{action.name}" => {
34
+ "xmlns" => WsdlParser.target_namespace
35
+ }
36
+ }
37
+ }
38
+ }
39
+
40
+ if(!data.nil?)
41
+ data.each do |key, value|
42
+ build_param(body['soap:Envelope']['soap:Body']["#{action.name}"],action,key,value)
43
+ end
44
+ end
45
+
46
+ XmlSimple.xml_out(body, 'RootName' => nil)
47
+ end
48
+
49
+ # Parse the server response to hash that the user will work eith
50
+ # Params:
51
+ # +res+:: +HTTPI::Response+ object that represent the response from the server
52
+ # +action_name+:: the name of the action that the response is belongs to
53
+ def get_wcf_response(res,action_name)
54
+ #res.error?
55
+ if res.code.to_i >= 400
56
+ 'error please see body'
57
+ else
58
+ result = XmlSimple.xml_in(res.body)['Body'].first["#{action_name}Response"].first["#{action_name}Result"].first
59
+ if result.class == Hash
60
+ # I dont want to return the result xml attributes
61
+ result.select!{|k,v| v.class == Array}
62
+ end
63
+
64
+ result
65
+ end
66
+ end
67
+
68
+ # Adds to the action element in the +Hash+ and add the user send data to the hash
69
+ # Params:
70
+ # +action_element+:: the action element in the hash of the body
71
+ # +action+:: +SoapAction+ object that keep all the data about the soap action
72
+ # +key+:: the name of the parameter
73
+ # +value+:: the value of the parameter
74
+ def build_param(action_element,action,key,value)
75
+ if(action.parameters.nil?)
76
+ action_element["#{key}"] = ((value.is_a? Hash) ? data_to_arr(value) : [value])
77
+ else
78
+ current_param = action.parameters.select{|p| p.name.upcase == key.to_s.upcase}.first
79
+ action_element["#{key}"] = ((value.is_a? Hash) ? data_to_arr(value) : [value])
80
+
81
+ if !current_param.namespace.nil?
82
+ action_element["#{key}"].merge!("xmlns:#{@name_space}" => current_param.namespace)
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+
@@ -0,0 +1,9 @@
1
+ module Soap
2
+ class SoapAction
3
+ attr_accessor :name, :soap_action, :parameters
4
+
5
+ def self.parse()
6
+ #TODO:parse from xml to SoapParamter object
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module Soap
2
+ class SoapParamter
3
+ attr_accessor :name, :nullable, :type, :namespace
4
+
5
+ # Gets the xml element of the paramter and parse it to a +SoapParamter+ object
6
+ # Params:
7
+ # +param_element+:: +Hash+ that represent the xml element of the paramter
8
+ def self.parse(param_element)
9
+ param = SoapParamter.new
10
+ param.name = param_element['name']
11
+ param.type = param_element['type'].split(':').last
12
+ yield param if block_given?
13
+
14
+ param
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ module Web
2
+ # the secutry protocols that have support
3
+ module SecutryProtocol
4
+ NTLM = 0
5
+ GGS_API = 1
6
+ KERBEROS = 1
7
+ BASIC = 2
8
+ DIGEST = 3
9
+ end
10
+ end
@@ -0,0 +1,88 @@
1
+ require 'httpi'
2
+ require_relative './secutry_protocols'
3
+
4
+ # Handle all the communication to the service
5
+ module Web
6
+ # Send Http get rquest to a url and return his result via +HTTPI+
7
+ # Params:
8
+ # +url+:: the url to send the request to
9
+ # +headers+:: hash that keeps the headers that need to be send to the service
10
+ def get_web_response(url,headers)
11
+ request = HTTPI::Request.new(url)
12
+
13
+ request.headers = headers
14
+ response = HTTPI.get(request)
15
+
16
+ response
17
+ end
18
+
19
+ # Send http request to the service
20
+ # Params:
21
+ # +url+:: the url to send the request to
22
+ # +headers+:: hash that keeps the headers that need to be send to the service
23
+ # +body+:: the body of the HTTP request
24
+ # +args+:: metadata that indicate wich autountication to use
25
+ def send_message_to_wcf(url,headers,body,*args)
26
+ request = HTTPI::Request.new(url)
27
+ request.headers = headers
28
+ request.body = body
29
+
30
+ #TODO: change to user self.send('use_'+)
31
+ case args.first
32
+ when SecutryProtocol::NTLM
33
+ use_ntlm(request,*args)
34
+ when SecutryProtocol::GGS_API
35
+ use_kerberos(request)
36
+ when SecutryProtocol::BASIC
37
+ use_basic(request,*args)
38
+ when SecutryProtocol::DIGEST
39
+ use_digest(request,*args)
40
+ end
41
+
42
+ response = HTTPI.post(request)
43
+ response
44
+ end
45
+
46
+ private
47
+ # Use ntlm auth in the request
48
+ # Params:
49
+ # +request+:: +HTTPI::Request+ request
50
+ # +args+:: keep the data that need to be uses for the NTLM auth
51
+ def use_ntlm(request,*args)
52
+ # the first is the security name
53
+ user = args[1]
54
+ password = args[2]
55
+ domain = args[3]
56
+
57
+ request.auth.ntlm(user,password,domain)# if request.auth.ntlm?
58
+ end
59
+
60
+ # Use kerberos auth in the request
61
+ # Params:
62
+ # +request+:: +HTTPI::Request+ request
63
+ def use_kerberos(request)
64
+ request.auth.gssnegotiate
65
+ end
66
+
67
+ # Use basic auth in the request
68
+ # Params:
69
+ # +request+:: +HTTPI::Request+ request
70
+ # +args+:: keep the data that need to be uses for the basic auth
71
+ def use_basic(request,*args)
72
+ user = args[1]
73
+ password = args[2]
74
+
75
+ request.auth.basic(user,password)
76
+ end
77
+
78
+ # Use digest auth in the request
79
+ # Params:
80
+ # +request+:: +HTTPI::Request+ request
81
+ # +args+:: keep the data that need to be uses for the digest auth
82
+ def use_digest(request,*args)
83
+ user = args[1]
84
+ password = args[2]
85
+
86
+ request.auth.digest(user,password)
87
+ end
88
+ end
data/lib/wsdl/wsdl.rb ADDED
@@ -0,0 +1,7 @@
1
+ require_relative '..\wsdl\wsdl_parser'
2
+
3
+ module Wsdl
4
+ class Wsdl
5
+ attr_accessor :actions, :target_namespace, :location_address
6
+ end
7
+ end
@@ -0,0 +1,151 @@
1
+ require 'xmlsimple'
2
+ require_relative '..\soap\soap'
3
+ require_relative '..\web\web_request_handler'
4
+ include Soap
5
+ include Web
6
+
7
+ module Wsdl
8
+ class WsdlParser
9
+ # Parse the service wsdl to a +Wsdl+ object
10
+ # Params :
11
+ # +service+:: the url of the service
12
+ def self.parse(service)
13
+ @service = service
14
+ wsdl_xml = get_serivce_data('wsdl')
15
+ doc = XmlSimple.xml_in(wsdl_xml)
16
+
17
+ res = Wsdl.new
18
+ res.actions = get_soap_actions(doc)
19
+ res.location_address = get_location_address(doc)
20
+ res.target_namespace = doc['targetNamespace']
21
+
22
+ res
23
+ end
24
+
25
+ # Return the target namespace of the last wsdl parser.
26
+ # TODO: Remove this method and user tel +Wsdl+ it self to get the target namespace
27
+ def self.target_namespace
28
+ @@target_namespace
29
+ end
30
+
31
+ private
32
+ # Return the service data for specified extension (wsdl, xsd=xsd0, etc)
33
+ # Params:
34
+ # +extension+:: the extension the query the service with (wsdl, xsd=xsd0, etc)
35
+ def self.get_serivce_data(extension)
36
+ uri = URI("#{@service}")
37
+
38
+ res = get_web_response("#{@service}?#{extension}",
39
+ {"Accept" => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
40
+ "Accept-Encoding" => 'gzip,deflate,sdch'})
41
+ res.body
42
+ end
43
+
44
+ # ???
45
+ def self.get_action_datacontact(action_name)
46
+ if @xsd_namespace.nil?
47
+ xsd0 = get_serivce_data('xsd=xsd0')
48
+ doc = XmlSimple.xml_in(xsd0)
49
+
50
+ import = doc['import']
51
+ @xsd_namespace = (import.first['namespace'] unless import.nil?)
52
+ end
53
+
54
+ @xsd_namespace
55
+ end
56
+
57
+ # Return list of +SoapAction+
58
+ # Params:
59
+ # +doc+:: +Hash+ that represent the wsdl xml
60
+ def self.get_soap_actions(doc)
61
+ result = []
62
+
63
+ @@target_namespace = doc['targetNamespace']
64
+ should_read_from_xsd = !doc['types'].first['schema'].first['import'].nil?
65
+
66
+ binding = doc['binding'].first
67
+ binding['operation'].each do |opp|
68
+ action = SoapAction.new
69
+
70
+ action.name = opp['name']
71
+ action.soap_action = opp['operation'].first['soapAction']
72
+ action.parameters = get_action_params(action.name, doc, should_read_from_xsd)
73
+
74
+ result << action
75
+ end
76
+
77
+ result
78
+ end
79
+
80
+ # Return the location address of the service
81
+ # Params:
82
+ # +doc+:: +Hash+ that represent the wsdl xml
83
+ def self.get_location_address(doc)
84
+ service = doc['service']
85
+ location = service.first['port'].first['address'].first['location']
86
+
87
+ location
88
+ end
89
+
90
+ # Return the parameters that the soap actiop requires as list of +SoapParamter+ objects
91
+ # Params :
92
+ # +action_name+:: the name of the soap action
93
+ # +doc+:: hash the represent the WSDL
94
+ # +should_read_from_xsd+:: boolean that indicates whether it should read the parameters from the wsdl or imported xsd
95
+ def self.get_action_params(action_name,doc,should_read_from_xsd)
96
+ if(should_read_from_xsd)
97
+ get_action_params_from_xsd(action_name)
98
+ else
99
+ get_action_params_from_wsdl(action_name,doc)
100
+ end
101
+ end
102
+
103
+ # Parse the soap action element in the wsdl and return the parameters that the soap actiop requires as list of +SoapParamter+ objects
104
+ # Params:
105
+ # +action_name+:: the name of the soap action
106
+ # +doc+:: hash the represent the WSDL
107
+ def self.get_action_params_from_wsdl(action_name, doc)
108
+ #puts opp['input'].first
109
+ if @schema.nil?
110
+ @schema = doc['types'].first['schema'].first
111
+ end
112
+
113
+ action_element = @schema['element'].select{|e| e['name'] == action_name}.first
114
+ action_params_elements = action_element['complexType'].first['sequence'].first['element']
115
+
116
+ action_params_elements.map do |element|
117
+ SoapParamter.parse(element) do |param|
118
+ param.nullable = ['minOccurs'] == 0
119
+ end
120
+ end
121
+ end
122
+
123
+ # Parse the imported xsd and return the parameters that the soap actiop requires as list of +SoapParamter+ objects
124
+ # Params:
125
+ # +action_name+:: the name of the soap action
126
+ def self.get_action_params_from_xsd(action_name)
127
+ if @elements.nil?
128
+ #@elements = {}
129
+ xsd0 = get_serivce_data('xsd=xsd0')
130
+ doc = XmlSimple.xml_in(xsd0)
131
+
132
+ @elements = doc['element']
133
+
134
+ # the page dose not have imported shceme
135
+ return nil if @elements.nil?
136
+ end
137
+
138
+ element = @elements.select{|e| e['name'] == action_name}.first
139
+ sequence = element['complexType'].first['sequence'].first
140
+
141
+ return [] if sequence['element'].nil?
142
+ sequence['element'].map do |e|
143
+ SoapParamter.parse(e) do |param|
144
+ param.nullable = e['nillable']
145
+ namespace_element = e.select{|key,value| key.match(/xmlns(.*)/)}.first
146
+ (param.namespace = namespace_element[1]) unless namespace_element.nil?
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby2soap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Eric Feldman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: xml-simple
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httpi
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: enable communication between ruby and soap services
42
+ email: ericfeldman93@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - lib/ruby2soap.rb
48
+ - lib/soap/soap.rb
49
+ - lib/soap/soap_action.rb
50
+ - lib/soap/soap_parameter.rb
51
+ - lib/web/secutry_protocols.rb
52
+ - lib/web/web_request_handler.rb
53
+ - lib/wsdl/wsdl.rb
54
+ - lib/wsdl/wsdl_parser.rb
55
+ homepage: https://github.com/ericman93/ruby2soap
56
+ licenses: []
57
+ metadata: {}
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 2.2.1
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Communication between ruby and soap services
78
+ test_files: []