serviceproxy 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ LICENSE
2
+
3
+ The MIT License
4
+
5
+ Copyright (c) 2008 Jeremy Durham
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,27 @@
1
+ ServiceProxy
2
+
3
+ ServiceProxy is a lightweight SOAP library for Ruby.
4
+
5
+ HOW IT WORKS
6
+
7
+ Loading the library:
8
+
9
+ require 'rubygems'
10
+ require 'service_proxy/base'
11
+
12
+ GENERATING A PROXY
13
+
14
+ ServiceProxy comes with a simple generator to get started. It can be invoked
15
+ as follows:
16
+
17
+ wsdl2proxy [wsdl]
18
+
19
+ This will generate a file named default.rb, in the current directory. The class
20
+ will be named GeneratedService, and will define build and parse methods for all
21
+ of the available service methods.
22
+
23
+ Please refer to the specs for extended usage examples.
24
+
25
+ CONTRIBUTORS
26
+
27
+ Rich Cavanaugh
data/Rakefile ADDED
@@ -0,0 +1,95 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'rake/rdoctask'
5
+ require 'spec/rake/spectask'
6
+ require File.join(File.dirname(__FILE__), 'lib', 'service_proxy', 'base')
7
+
8
+ NAME = "serviceproxy"
9
+ AUTHOR = "Jeremy Durham"
10
+ EMAIL = "jeremydurham@gmail.com"
11
+ HOMEPAGE = ""
12
+ SUMMARY = "Lightweight SOAP library for Ruby"
13
+
14
+ # Used by release task
15
+ GEM_NAME = NAME
16
+ PROJECT_URL = HOMEPAGE
17
+ PROJECT_SUMMARY = SUMMARY
18
+ PROJECT_DESCRIPTION = SUMMARY
19
+
20
+ PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
21
+ GEM_VERSION = ServiceProxy::Base::VERSION + PKG_BUILD
22
+ RELEASE_NAME = "REL #{GEM_VERSION}"
23
+ #
24
+ # ==== Gemspec and installation
25
+ #
26
+
27
+ spec = Gem::Specification.new do |s|
28
+ s.name = NAME
29
+ s.version = ServiceProxy::Base::VERSION
30
+ s.platform = Gem::Platform::RUBY
31
+ s.has_rdoc = true
32
+ s.extra_rdoc_files = ["README", "LICENSE"]
33
+ s.summary = SUMMARY
34
+ s.description = s.summary
35
+ s.author = AUTHOR
36
+ s.email = EMAIL
37
+ s.homepage = HOMEPAGE
38
+ s.require_path = 'lib'
39
+ s.executables = ['wsdl2proxy']
40
+ s.files = %w(LICENSE README Rakefile) + Dir.glob("{lib,spec}/**/*")
41
+
42
+ s.add_dependency "nokogiri"
43
+ s.add_dependency "hpricot"
44
+ end
45
+
46
+ Rake::GemPackageTask.new(spec) do |pkg|
47
+ pkg.gem_spec = spec
48
+ end
49
+
50
+ desc "install the gem locally"
51
+ task :install => [:clean, :package] do
52
+ sh %{sudo gem install pkg/#{NAME}-#{ServiceProxy::Base::VERSION} --no-update-sources}
53
+ end
54
+
55
+ desc "create a gemspec file"
56
+ task :make_spec do
57
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
58
+ file.puts spec.to_ruby
59
+ end
60
+ end
61
+
62
+ desc "Run coverage suite"
63
+ task :rcov do
64
+ require 'fileutils'
65
+ FileUtils.rm_rf("coverage") if File.directory?("coverage")
66
+ FileUtils.mkdir("coverage")
67
+ path = File.expand_path(Dir.pwd)
68
+ files = Dir["spec/**/*_spec.rb"]
69
+ files.each do |spec|
70
+ puts "Getting coverage for #{File.expand_path(spec)}"
71
+ command = %{rcov #{File.expand_path(spec)} --aggregate #{path}/coverage/data.data}
72
+ command += " --no-html" unless spec == files.last
73
+ `#{command} 2>&1`
74
+ end
75
+ end
76
+
77
+ file_list = FileList['spec/**/*_spec.rb']
78
+
79
+ desc "Run all examples"
80
+ Spec::Rake::SpecTask.new('spec') do |t|
81
+ t.spec_files = file_list
82
+ end
83
+
84
+ namespace :spec do
85
+ desc "Run all examples with RCov"
86
+ Spec::Rake::SpecTask.new('rcov') do |t|
87
+ t.spec_files = file_list
88
+ t.rcov = true
89
+ t.rcov_dir = "doc/coverage"
90
+ t.rcov_opts = ['--exclude', 'spec']
91
+ end
92
+ end
93
+
94
+ desc 'Default: run unit tests.'
95
+ task :default => 'spec'
data/bin/wsdl2proxy ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'service_proxy/base'
5
+
6
+ def underscore(camel_cased_word)
7
+ camel_cased_word.to_s.gsub(/::/, '/').
8
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
9
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
10
+ tr("-", "_").
11
+ downcase
12
+ end
13
+
14
+ unless ARGV.size > 0
15
+ puts "Usage: #{$0} [endpoint]"
16
+ exit!
17
+ end
18
+
19
+ template_filename = File.dirname(__FILE__) + '/../lib/templates/proxy.rbt'
20
+ proxy = ServiceProxy::Base.new(ARGV[0])
21
+ output_filename = 'default.rb'
22
+ output_klass_name = 'GeneratedService'
23
+ output = ''
24
+ proxy.service_methods.each do |service_method|
25
+ output << <<-EOS
26
+
27
+ def build_#{underscore(service_method)}(options)
28
+ soap_envelope(options) do |xml|
29
+ end
30
+ end
31
+
32
+ def parse_#{underscore(service_method)}(response)
33
+ Hpricot.XML(response.body)
34
+ end
35
+ EOS
36
+ end
37
+ template = File.read(template_filename)
38
+ template.gsub!(/%name%/, output_klass_name)
39
+ template.gsub!(/%body%/, output)
40
+ File.open(output_filename, 'w') { |f| f.puts template }
41
+ puts "Generated proxy #{output_filename} - You can use the proxy by executing #{output_klass_name}.new('#{ARGV[0]}')"
@@ -0,0 +1,154 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'uri'
4
+
5
+ begin
6
+ require 'nokogiri'
7
+ require 'builder'
8
+ rescue LoadError
9
+ puts "Could not load nokogiri or builder. Please make sure they are installed and in your $LOAD_PATH."
10
+ end
11
+
12
+ module ServiceProxy
13
+ class Base
14
+ VERSION = '0.1.4'
15
+
16
+ attr_accessor :endpoint, :service_methods, :soap_actions, :service_uri, :http, :service_http, :uri, :debug, :wsdl, :target_namespace, :service_ports
17
+
18
+ def initialize(endpoint)
19
+ self.endpoint = endpoint
20
+ self.setup
21
+ end
22
+
23
+ def call_service(options)
24
+ method = options[:method]
25
+ headers = { 'content-type' => 'text/xml; charset=utf-8', 'SOAPAction' => self.soap_actions[method] }
26
+ body = build_request(method, options)
27
+ response = self.service_http.request_post(self.service_uri.path, body, headers)
28
+ parse_response(method, response)
29
+ end
30
+
31
+ protected
32
+
33
+ def setup
34
+ self.soap_actions = {}
35
+ self.service_methods = []
36
+ setup_uri
37
+ self.http = setup_http(self.uri)
38
+ get_wsdl
39
+ parse_wsdl
40
+ setup_namespace
41
+ end
42
+
43
+ def service_uri
44
+ @service_uri ||= self.respond_to?(:service_port) ? self.service_port : self.uri
45
+ end
46
+
47
+ def service_http
48
+ @service_http ||= unless self.service_uri == self.uri
49
+ local_http = self.setup_http(self.service_uri)
50
+ setup_https(local_http) if self.service_uri.scheme == 'https'
51
+ local_http
52
+ else
53
+ self.http
54
+ end
55
+ end
56
+
57
+ def setup_http(local_uri)
58
+ raise ArgumentError, "Endpoint URI must be valid" unless local_uri.scheme
59
+ local_http = Net::HTTP.new(local_uri.host, local_uri.port)
60
+ setup_https(local_http) if local_uri.scheme == 'https'
61
+ local_http.set_debug_output(STDOUT) if self.debug
62
+ local_http.read_timeout = 5
63
+ local_http
64
+ end
65
+
66
+ def setup_https(local_http)
67
+ local_http.use_ssl = true
68
+ local_http.verify_mode = OpenSSL::SSL::VERIFY_NONE
69
+ end
70
+
71
+ private
72
+
73
+ def setup_uri
74
+ self.uri = URI.parse(self.endpoint)
75
+ end
76
+
77
+ def get_wsdl
78
+ response = self.http.get("#{self.uri.path}?#{self.uri.query}")
79
+ self.wsdl = Nokogiri.XML(response.body)
80
+ end
81
+
82
+ def parse_wsdl
83
+ method_list = []
84
+ self.wsdl.xpath('//*[name()="soap:operation"]').each do |operation|
85
+ operation_name = operation.parent.get_attribute('name')
86
+ method_list << operation_name
87
+ self.soap_actions[operation_name] = operation.get_attribute('soapAction')
88
+ end
89
+ raise RuntimeError, "Could not parse WSDL" if method_list.empty?
90
+ self.service_methods = method_list.sort
91
+
92
+ port_list = {}
93
+ self.wsdl.xpath('//wsdl:port', {"xmlns:wsdl" => 'http://schemas.xmlsoap.org/wsdl/'}).each do |port|
94
+ name = underscore(port['name'])
95
+ location = port.xpath('./*[@location]').first['location']
96
+ port_list[name] = location
97
+ end
98
+ self.service_ports = port_list
99
+ end
100
+
101
+ def setup_namespace
102
+ self.target_namespace = self.wsdl.namespaces['xmlns:tns']
103
+ end
104
+
105
+ def build_request(method, options)
106
+ builder = underscore("build_#{method}")
107
+ self.respond_to?(builder) ? self.send(builder, options).target! :
108
+ soap_envelope(options).target!
109
+ end
110
+
111
+ def parse_response(method, response)
112
+ parser = underscore("parse_#{method}")
113
+ self.respond_to?(parser) ? self.send(parser, response) :
114
+ raise(NoMethodError, "You must define the parse method: #{parser}")
115
+ end
116
+
117
+ def soap_envelope(options, &block)
118
+ xsd = 'http://www.w3.org/2001/XMLSchema'
119
+ env = 'http://schemas.xmlsoap.org/soap/envelope/'
120
+ xsi = 'http://www.w3.org/2001/XMLSchema-instance'
121
+ xml = Builder::XmlMarkup.new
122
+ xml.env(:Envelope, 'xmlns:xsd' => xsd, 'xmlns:env' => env, 'xmlns:xsi' => xsi) do
123
+ xml.env(:Body) do
124
+ xml.__send__(options[:method].to_sym, "xmlns" => self.target_namespace) do
125
+ yield xml if block_given?
126
+ end
127
+ end
128
+ end
129
+ xml
130
+ end
131
+
132
+ def method_missing(method, *args)
133
+ method_name = method.to_s
134
+ case method_name
135
+ when /_uri$/
136
+ sp_name = method_name.gsub(/_uri$/, '')
137
+ super unless self.service_ports.has_key?(sp_name)
138
+ URI.parse(self.service_ports[sp_name])
139
+ else
140
+ options = args.pop || {}
141
+ super unless self.service_methods.include?(method_name)
142
+ call_service(options.update(:method => method_name))
143
+ end
144
+ end
145
+
146
+ def underscore(camel_cased_word)
147
+ camel_cased_word.to_s.gsub(/::/, '/').
148
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
149
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
150
+ tr("-", "_").
151
+ downcase
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'service_proxy/base'
3
+ require 'hpricot'
4
+
5
+ class %name% < ServiceProxy::Base
6
+ %body%
7
+ end
@@ -0,0 +1,48 @@
1
+ require 'hpricot'
2
+
3
+ # Service Endpoints
4
+ class ISBNService < ServiceProxy::Base
5
+
6
+ def build_is_valid_isbn13(options)
7
+ soap_envelope(options) do |xml|
8
+ xml.sISBN(options[:isbn])
9
+ end
10
+ end
11
+
12
+ def parse_is_valid_isbn13(response)
13
+ xml = Hpricot.XML(response.body)
14
+ xml.at("m:IsValidISBN13Result").inner_text == 'true' ? true : false
15
+ end
16
+
17
+ def service_port
18
+ local_uri = URI.parse(self.isbn_service_soap_uri.to_s)
19
+ local_uri.path << "?dummy=1"
20
+ local_uri
21
+ end
22
+ end
23
+
24
+ class SHAGeneratorService < ServiceProxy::Base
25
+
26
+ def build_gen_ssha(options)
27
+ soap_envelope(options) do |xml|
28
+ xml.text(options[:text])
29
+ xml.hashtype(options[:hash_type])
30
+ end
31
+ end
32
+
33
+ def parse_gen_ssha(response)
34
+ xml = Hpricot.XML(response.body)
35
+ xml.at("return").inner_text
36
+ end
37
+ end
38
+
39
+ class InvalidSHAGeneratorService < ServiceProxy::Base
40
+
41
+ def build_gen_ssha(options)
42
+ soap_envelope(options) do |xml|
43
+ xml.text(options[:text])
44
+ xml.hashtype(options[:hash_type])
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,65 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'lib/service_proxy/base'
4
+ require 'spec/service_helper'
5
+
6
+ describe ServiceProxy do
7
+ it "should raise on an invalid URI" do
8
+ lambda { ServiceProxy::Base.new('bacon') }.should raise_error(ArgumentError)
9
+ end
10
+
11
+ it "should raise on invalid WSDL" do
12
+ lambda { ServiceProxy::Base.new('http://www.yahoo.com') }.should raise_error(RuntimeError)
13
+ end
14
+
15
+ describe "connecting to an ISBN validator" do
16
+ before do
17
+ @proxy = ISBNService.new('http://webservices.daehosting.com/services/isbnservice.wso?WSDL')
18
+ end
19
+
20
+ describe "calling IsValidISBN13" do
21
+ it "should return true for a valid ISBN" do
22
+ @proxy.IsValidISBN13(:isbn => '978-0977616633').should == true
23
+ end
24
+
25
+ it "should return false for an invalid ISBN" do
26
+ @proxy.IsValidISBN13(:isbn => '999-9999391939').should == false
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "connecting to the SHA hash generator Service" do
32
+ before do
33
+ @proxy = SHAGeneratorService.new('https://sec.neurofuzz-software.com/paos/genSSHA-SOAP.php?wsdl')
34
+ end
35
+
36
+ it "should be SSL" do
37
+ @proxy.http.use_ssl.should be_true
38
+ end
39
+
40
+ it "should generate a SSH hash" do
41
+ result = @proxy.genSSHA(:text => 'hello world', :hash_type => 'sha512')
42
+ result.should =~ /^[{SSHA512}]/
43
+ end
44
+ end
45
+
46
+ describe "making a service call without a parse method" do
47
+ before do
48
+ @proxy = InvalidSHAGeneratorService.new('https://sec.neurofuzz-software.com/paos/genSSHA-SOAP.php?wsdl')
49
+ end
50
+
51
+ it "should raise a no method error" do
52
+ lambda { result = @proxy.genSSHA(:text => 'hello world', :hash_type => 'sha512') }.should raise_error(NoMethodError)
53
+ end
54
+ end
55
+
56
+ describe "using the #service_port hook" do
57
+ before do
58
+ @proxy = ISBNService.new('http://webservices.daehosting.com/services/isbnservice.wso?WSDL')
59
+ end
60
+
61
+ it "should have the dummy query argument" do
62
+ @proxy.send(:service_uri).path.should match(/\?dummy=1/)
63
+ end
64
+ end
65
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: serviceproxy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Durham
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-13 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nokogiri
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hpricot
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: builder
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: Lightweight SOAP library for Ruby
46
+ email: jeremydurham@gmail.com
47
+ executables:
48
+ - wsdl2proxy
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - README
53
+ - LICENSE
54
+ files:
55
+ - LICENSE
56
+ - README
57
+ - Rakefile
58
+ - lib/service_proxy/base.rb
59
+ - lib/templates/proxy.rbt
60
+ - spec/service_helper.rb
61
+ - spec/service_proxy_spec.rb
62
+ has_rdoc: true
63
+ homepage: ""
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.5
87
+ signing_key:
88
+ specification_version: 2
89
+ summary: Lightweight SOAP library for Ruby
90
+ test_files: []
91
+