hprose 1.4.1

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