hprose 1.4.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.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Hprose for Ruby
2
+
3
+ *Hprose* is a High Performance Remote Object Service Engine.
4
+
5
+ It is a modern, lightweight, cross-language, cross-platform, object-oriented, high performance, remote dynamic communication middleware. It is not only easy to use, but powerful. You just need a little time to learn, then you can use it to easily construct cross language cross platform distributed application system.
6
+
7
+ *Hprose* supports many programming languages, for example:
8
+
9
+ * AAuto Quicker
10
+ * ActionScript
11
+ * ASP
12
+ * C++
13
+ * Dart
14
+ * Delphi/Free Pascal
15
+ * dotNET(C#, Visual Basic...)
16
+ * Golang
17
+ * Java
18
+ * JavaScript
19
+ * Node.js
20
+ * Objective-C
21
+ * Perl
22
+ * PHP
23
+ * Python
24
+ * Ruby
25
+ * ...
26
+
27
+ Through *Hprose*, You can conveniently and efficiently intercommunicate between those programming languages.
28
+
29
+ This project is the implementation of Hprose for Ruby.
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'hprose'
3
+
4
+ client = HproseHttpClient.new('http://localhost:3000/')
5
+ def error(name, e)
6
+ puts name
7
+ puts e
8
+ end
9
+ client.onerror = :error
10
+
11
+ math = client.use_service(nil, :math)
12
+
13
+ client.hello('World') { |result|
14
+ puts result
15
+ }
16
+
17
+ math.add(1, 2) { |result|
18
+ puts result
19
+ }.join
20
+
21
+ math.sub(1, 2) { |result|
22
+ puts result
23
+ }.join
24
+
25
+ puts client.sum(1,3,4,5,6,7)
26
+ user = client.getUser()
27
+ puts user.name
28
+ puts user.age
29
+
30
+ puts client.hi('hprose')
31
+ puts client.push([user, user, user])
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rack'
3
+ require 'hprose'
4
+
5
+ def hello(name)
6
+ return 'hello ' << name << '!'
7
+ end
8
+
9
+ class User
10
+ def initialize()
11
+ @name = "Tom"
12
+ @age = 28
13
+ end
14
+ end
15
+
16
+ def getUser()
17
+ return User.new()
18
+ end
19
+
20
+
21
+ class MyService
22
+ def add(a, b)
23
+ return a + b
24
+ end
25
+ def sub(a, b)
26
+ return a - b
27
+ end
28
+ end
29
+
30
+ def mf(name, args)
31
+ return name << " => " << HproseFormatter.serialize(args)
32
+ end
33
+
34
+ HproseClassManager.register(User, "User")
35
+
36
+ app = HproseHttpService.new()
37
+
38
+ app.add(:hello)
39
+ app.add(:sum) { |*num|
40
+ result = 0
41
+ num.each { |item| result += item }
42
+ result
43
+ }
44
+ app.add(:getUser)
45
+ app.add_missing_function(:mf)
46
+ app.add(MyService.new, :math)
47
+ app.debug = true
48
+ Rack::Handler::WEBrick.run(app, {:Port => 3000})
@@ -0,0 +1,156 @@
1
+ ############################################################
2
+ # #
3
+ # hprose #
4
+ # #
5
+ # Official WebSite: http://www.hprose.com/ #
6
+ # http://www.hprose.net/ #
7
+ # http://www.hprose.org/ #
8
+ # #
9
+ ############################################################
10
+
11
+ ############################################################
12
+ # #
13
+ # hprose/client.rb #
14
+ # #
15
+ # hprose client for ruby #
16
+ # #
17
+ # LastModified: Mar 8, 2014 #
18
+ # Author: Ma Bingyao <andot@hprose.com> #
19
+ # #
20
+ ############################################################
21
+
22
+ require "hprose/common"
23
+ require "hprose/io"
24
+
25
+ module Hprose
26
+ class Client
27
+ include Tags
28
+ include ResultMode
29
+ public
30
+ def initialize(uri = nil)
31
+ @onerror = nil
32
+ @filter = Filter.new
33
+ @simple = false
34
+ self.uri = uri
35
+ end
36
+ def uri=(uri)
37
+ @uri = URI.parse(uri) unless uri.nil?
38
+ end
39
+ attr_reader :uri
40
+ attr_accessor :filter, :simple
41
+ def onerror(&block)
42
+ @onerror = block if block_given?
43
+ @onerror
44
+ end
45
+ def onerror=(error_handler)
46
+ error_handler = error_handler.to_sym if error_handler.is_a?(String)
47
+ if error_handler.is_a?(Symbol) then
48
+ error_handler = Object.method(error_handler)
49
+ end
50
+ @onerror = error_handler
51
+ end
52
+ def use_service(uri = nil, namespace = nil)
53
+ self.uri = uri
54
+ Proxy.new(self, namespace)
55
+ end
56
+ def [](namespace)
57
+ Proxy.new(self, namespace)
58
+ end
59
+ def invoke(methodname, args = [], byref = false, resultMode = Normal, simple = nil, &block)
60
+ simple = @simple if simple.nil?
61
+ if block_given? then
62
+ Thread.start do
63
+ begin
64
+ result = do_invoke(methodname, args, byref, resultMode, simple)
65
+ case block.arity
66
+ when 0 then yield
67
+ when 1 then yield result
68
+ when 2 then yield result, args
69
+ end
70
+ rescue ::Exception => e
71
+ @onerror.call(methodname, e) if (@onerror.is_a?(Proc) or
72
+ @onerror.is_a?(Method) or
73
+ @onerror.respond_to?(:call))
74
+ end
75
+ end
76
+ else
77
+ return do_invoke(methodname, args, byref, resultMode, simple)
78
+ end
79
+ end
80
+ protected
81
+ def send_and_receive(data)
82
+ raise NotImplementedError.new("#{self.class.name}#send_and_receive is an abstract method")
83
+ end
84
+ private
85
+ def do_output(methodname, args, byref, simple)
86
+ stream = StringIO.new
87
+ writer = Writer.new(stream, simple)
88
+ stream.putc(TagCall)
89
+ writer.write_string(methodname.to_s)
90
+ if (args.size > 0 or byref) then
91
+ writer.reset
92
+ writer.write_list(args)
93
+ writer.write_boolean(true) if byref
94
+ end
95
+ stream.putc(TagEnd)
96
+ data = @filter.output_filter(stream.string)
97
+ stream.close
98
+ return data
99
+ end
100
+ def do_input(data, args, resultMode)
101
+ data = @filter.input_filter(data)
102
+ raise Exception.exception("Wrong Response: \r\n#{data}") if data[data.size - 1].ord != TagEnd
103
+ return data if resultMode == RawWithEndTag
104
+ return data.chop! if resultMode == Raw
105
+ stream = StringIO.new(data, 'rb')
106
+ reader = Reader.new(stream)
107
+ result = nil
108
+ while (tag = stream.getbyte) != TagEnd do
109
+ case tag
110
+ when TagResult then
111
+ if resultMode == Normal then
112
+ reader.reset
113
+ result = reader.unserialize
114
+ else
115
+ s = reader.read_raw
116
+ result = s.string
117
+ s.close
118
+ end
119
+ when TagArgument then
120
+ reader.reset
121
+ a = reader.read_list
122
+ args.each_index { |i| args[i] = a[i] }
123
+ when TagError then
124
+ reader.reset
125
+ result = Exception.exception(reader.read_string())
126
+ else
127
+ raise Exception.exception("Wrong Response: \r\n#{data}")
128
+ end
129
+ end
130
+ return result
131
+ end
132
+ def do_invoke(methodname, args, byref, resultMode, simple)
133
+ data = do_output(methodname, args, byref, simple)
134
+ result = do_input(send_and_receive(data), args, resultMode)
135
+ raise result if result.is_a?(Exception)
136
+ return result
137
+ end
138
+ def method_missing(methodname, *args, &block)
139
+ self.invoke(methodname, args, &block)
140
+ end
141
+
142
+ class Proxy
143
+ def initialize(client, namespace = nil)
144
+ @client = client
145
+ @namespace = namespace
146
+ end
147
+ def [](namespace)
148
+ Proxy.new(@client, @namespace.to_s + '_' + namespace.to_s)
149
+ end
150
+ def method_missing(methodname, *args, &block)
151
+ methodname = @namespace.to_s + '_' + methodname.to_s unless @namespace.nil?
152
+ @client.invoke(methodname, args, &block)
153
+ end
154
+ end # class Proxy
155
+ end # class Client
156
+ end # module Hprose
@@ -0,0 +1,41 @@
1
+ ############################################################
2
+ # #
3
+ # hprose #
4
+ # #
5
+ # Official WebSite: http://www.hprose.com/ #
6
+ # http://www.hprose.net/ #
7
+ # http://www.hprose.org/ #
8
+ # #
9
+ ############################################################
10
+
11
+ ############################################################
12
+ # #
13
+ # hprose/common.rb #
14
+ # #
15
+ # hprose common library for ruby #
16
+ # #
17
+ # LastModified: Dec 2, 2012 #
18
+ # Author: Ma Bingyao <andot@hprose.com> #
19
+ # #
20
+ ############################################################
21
+
22
+ module Hprose
23
+ class Exception < Exception; end
24
+
25
+ module ResultMode
26
+ Normal = 0
27
+ Serialized = 1
28
+ Raw = 2
29
+ RawWithEndTag = 3
30
+ end
31
+
32
+ class Filter
33
+ def input_filter(data)
34
+ return data
35
+ end
36
+ def output_filter(data)
37
+ return data
38
+ end
39
+ end
40
+
41
+ end # module Hprose
@@ -0,0 +1,141 @@
1
+ ############################################################
2
+ # #
3
+ # hprose #
4
+ # #
5
+ # Official WebSite: http://www.hprose.com/ #
6
+ # http://www.hprose.net/ #
7
+ # http://www.hprose.org/ #
8
+ # #
9
+ ############################################################
10
+
11
+ ############################################################
12
+ # #
13
+ # hprose/httpclient.rb #
14
+ # #
15
+ # hprose http client for ruby #
16
+ # #
17
+ # LastModified: Mar 8, 2014 #
18
+ # Author: Ma Bingyao <andot@hprose.com> #
19
+ # #
20
+ ############################################################
21
+
22
+ require "hprose/client"
23
+ require "net/http"
24
+ require "net/https"
25
+ require "uri"
26
+
27
+ module Hprose
28
+ class HttpClient < Client
29
+ include Tags
30
+ @@cookie_manager = {}
31
+ @@cookie_manager_mutex = Mutex.new
32
+ public
33
+ def initialize(uri = nil)
34
+ super
35
+ Net::HTTP.version_1_2
36
+ @http = Net::HTTP
37
+ @header = {}
38
+ @timeout = 30
39
+ @keepalive = false
40
+ @keepalive_timeout = 300
41
+ end
42
+ attr_reader :header
43
+ attr_accessor :timeout, :keepalive, :keepalive_timeout
44
+ def proxy=(proxy)
45
+ @http = case proxy
46
+ when Net::HTTP then
47
+ proxy
48
+ when String then
49
+ uri = URI.parse(proxy)
50
+ Net::HTTP::Proxy(uri.host, uri.port, uri.user, uri.password)
51
+ else
52
+ proxy.superclass == Net::HTTP ? proxy : Net::HTTP
53
+ end
54
+ end
55
+ protected
56
+ def send_and_receive(data)
57
+ httpclient = @http.new(@uri.host, @uri.port)
58
+ httpclient.open_timeout = @timeout
59
+ httpclient.read_timeout = @timeout
60
+ httpclient.use_ssl = (@uri.scheme == 'https')
61
+ #httpclient.set_debug_output $stderr
62
+ httpclient.start
63
+ headers = {'Content-Type' => 'application/hprose',
64
+ 'Connection' => 'close'}
65
+ if @keepalive then
66
+ headers['Connection'] = 'keep-alive'
67
+ headers['Keep-Alive'] = @keepalive_timeout.to_s
68
+ end
69
+ headers['Authorization'] = 'Basic ' << ["#{@uri.user}:#{@uri.password}"].pack('m').delete!("\n") unless @uri.user.nil? or @uri.password.nil?
70
+ @header.each { |name, value|
71
+ headers[name] = value
72
+ }
73
+ headers['Content-Length'] = data.size.to_s
74
+ headers['Cookie'] = _get_cookie(@uri.host.downcase, @uri.path, @uri.scheme == 'https')
75
+ reqpath = @uri.path
76
+ reqpath << '?' << @uri.query unless @uri.query.nil?
77
+ response = httpclient.request_post(reqpath, data, headers)
78
+ case response
79
+ when Net::HTTPSuccess then
80
+ cookielist = []
81
+ cookielist.concat(response['set-cookie'].split(',')) if response.key?('set-cookie')
82
+ cookielist.concat(response['set-cookie2'].split(',')) if response.key?('set-cookie2')
83
+ _set_cookie(cookielist, @uri.host.downcase)
84
+ return response.body
85
+ else
86
+ raise Exception.exception(response.message)
87
+ end
88
+ end
89
+ private
90
+ def _set_cookie(cookielist, host)
91
+ @@cookie_manager_mutex.synchronize do
92
+ cookielist.each do |cookies|
93
+ unless cookies == '' then
94
+ cookies = cookies.strip.split(';')
95
+ cookie = {}
96
+ value = cookies[0].strip.split('=', 2)
97
+ cookie['name'] = value[0]
98
+ cookie['value'] = value.size == 2 ? value[1] : ''
99
+ 1.upto(cookies.size - 1) do |i|
100
+ value = cookies[i].strip.split('=', 2)
101
+ cookie[value[0].upcase] = value.size == 2 ? value[1] : ''
102
+ end
103
+ # Tomcat can return SetCookie2 with path wrapped in "
104
+ if cookie.has_key?('PATH') then
105
+ cookie['PATH'][0] = '' if cookie['PATH'][0] == ?"
106
+ cookie['PATH'].chop! if cookie['PATH'][-1] == ?"
107
+ else
108
+ cookie['PATH'] = '/'
109
+ end
110
+ cookie['EXPIRES'] = Time.parse(cookie['EXPIRES']) if cookie.has_key?('EXPIRES')
111
+ cookie['DOMAIN'] = cookie.has_key?('DOMAIN') ? cookie['COMAIN'].downcase : host
112
+ cookie['SECURE'] = cookie.has_key?('SECURE')
113
+ @@cookie_manager[cookie['DOMAIN']] = {} unless @@cookie_manager.has_key?(cookie['DOMAIN'])
114
+ @@cookie_manager[cookie['DOMAIN']][cookie['name']] = cookie
115
+ end
116
+ end
117
+ end
118
+ end
119
+ def _get_cookie(host, path, secure)
120
+ cookies = []
121
+ @@cookie_manager_mutex.synchronize do
122
+ @@cookie_manager.each do |domain, cookielist|
123
+ if host =~ Regexp.new(Regexp.escape(domain) + '$') then
124
+ names = []
125
+ cookielist.each do |name, cookie|
126
+ if cookie.has_key?('EXPIRES') and Time.now <=> cookie['EXPIRES'] > 0 then
127
+ names << name
128
+ elsif path =~ Regexp.new('^' + Regexp.escape(cookie['PATH'])) then
129
+ if ((secure and cookie['SECURE']) or not cookie['SECURE']) and cookie['value'] != '' then
130
+ cookies << (cookie['name'] + '=' + cookie['value'])
131
+ end
132
+ end
133
+ end
134
+ names.each { |name| @@cookie_manager[domain].delete(name) }
135
+ end
136
+ end
137
+ end
138
+ return cookies.join('; ')
139
+ end
140
+ end # class HttpClient
141
+ end # module Hprose
@@ -0,0 +1,76 @@
1
+ ############################################################
2
+ # #
3
+ # hprose #
4
+ # #
5
+ # Official WebSite: http://www.hprose.com/ #
6
+ # http://www.hprose.net/ #
7
+ # http://www.hprose.org/ #
8
+ # #
9
+ ############################################################
10
+
11
+ ############################################################
12
+ # #
13
+ # hprose/httpservice.rb #
14
+ # #
15
+ # hprose http service for ruby #
16
+ # #
17
+ # LastModified: Mar 8, 2014 #
18
+ # Author: Ma Bingyao <andot@hprose.com> #
19
+ # #
20
+ ############################################################
21
+
22
+ require "hprose/io"
23
+ require "hprose/service"
24
+
25
+ module Hprose
26
+ class HttpService < Service
27
+ attr_accessor :crossdomain
28
+ attr_accessor :p3p
29
+ attr_accessor :get
30
+ attr_accessor :on_send_header
31
+ def initialize
32
+ super
33
+ @crossdomain = false
34
+ @p3p = false
35
+ @get = true
36
+ @on_send_header = nil
37
+ end
38
+ def call(context)
39
+ header = {'Content-Type' => 'text/plain'}
40
+ header['P3P'] = 'CP="CAO DSP COR CUR ADM DEV TAI PSA PSD ' +
41
+ 'IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi ' +
42
+ 'PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT ' +
43
+ 'STA POL HEA PRE GOV"' if @p3p
44
+ if @crossdomain then
45
+ origin = context["HTTP_ORIGIN"]
46
+ if (origin and origin != "null") then
47
+ header['Access-Control-Allow-Origin'] = origin
48
+ header['Access-Control-Allow-Credentials'] = 'true'
49
+ else
50
+ header['Access-Control-Allow-Origin'] = '*'
51
+ end
52
+ end
53
+ begin
54
+ statuscode = 200
55
+ @on_send_header.call(header) unless @on_send_header.nil?
56
+ if (context['REQUEST_METHOD'] == 'GET') and @get then
57
+ body = do_function_list
58
+ elsif (context['REQUEST_METHOD'] == 'POST') then
59
+ body = handle(context['rack.input'].read, context)
60
+ else
61
+ statuscode = 403
62
+ body = 'Forbidden'
63
+ end
64
+ rescue ::Exception => e
65
+ body = do_error(e)
66
+ end
67
+ header['Content-Length'] = body.size.to_s
68
+ return [statuscode, header, [body]]
69
+ end
70
+ protected
71
+ def fix_args(args, arity, context)
72
+ session = context['rack.session'] ? context['rack.session'] : {}
73
+ ((arity > 0) and (args.length + 1 == arity)) ? args + [session] : args
74
+ end
75
+ end # class HttpService
76
+ end # module Hprose