saorin 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/saorin.rb +0 -1
- data/lib/saorin/client.rb +6 -3
- data/lib/saorin/client/base.rb +92 -0
- data/lib/saorin/client/faraday.rb +32 -0
- data/lib/saorin/registerable.rb +31 -0
- data/lib/saorin/server.rb +6 -4
- data/lib/saorin/server/base.rb +86 -0
- data/lib/saorin/server/rack.rb +33 -0
- data/lib/saorin/version.rb +1 -1
- data/saorin.gemspec +0 -1
- data/spec/{adapter → server}/base_spec.rb +6 -3
- data/spec/{adapter/servers → server}/rack_spec.rb +2 -2
- metadata +13 -36
- data/lib/saorin/adapters.rb +0 -2
- data/lib/saorin/adapters/clients.rb +0 -10
- data/lib/saorin/adapters/clients/base.rb +0 -94
- data/lib/saorin/adapters/clients/faraday.rb +0 -32
- data/lib/saorin/adapters/registerable.rb +0 -33
- data/lib/saorin/adapters/servers.rb +0 -10
- data/lib/saorin/adapters/servers/base.rb +0 -88
- data/lib/saorin/adapters/servers/rack.rb +0 -33
- data/lib/saorin/adapters/servers/reel.rb +0 -37
- data/server.rb +0 -13
- data/spec/adapter/servers/reel_spec.rb +0 -11
data/lib/saorin.rb
CHANGED
data/lib/saorin/client.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
-
require 'saorin/
|
1
|
+
require 'saorin/registerable'
|
2
2
|
|
3
3
|
module Saorin
|
4
|
-
|
4
|
+
module Client
|
5
|
+
include Registerable
|
6
|
+
self.load_path = 'saorin/client'
|
7
|
+
|
5
8
|
class << self
|
6
9
|
def new(options = {}, &block)
|
7
10
|
adapter = options.delete(:adapter) || :faraday
|
8
|
-
adapter_class =
|
11
|
+
adapter_class = guess adapter
|
9
12
|
adapter_class.new options, &block
|
10
13
|
end
|
11
14
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
require 'saorin/request'
|
3
|
+
require 'saorin/response'
|
4
|
+
require 'saorin/client'
|
5
|
+
|
6
|
+
module Saorin
|
7
|
+
module Client
|
8
|
+
module Base
|
9
|
+
CONTENT_TYPE = 'application/json'.freeze
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(method, *args)
|
15
|
+
apply Saorin::Request.new(method, args, :id => seqid!)
|
16
|
+
end
|
17
|
+
|
18
|
+
def notify(method, *args)
|
19
|
+
apply Saorin::Request.new(method, args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def apply(request)
|
23
|
+
response = send_request request.to_json
|
24
|
+
content = process_response response
|
25
|
+
raise content if content.is_a?(Saorin::RPCError)
|
26
|
+
content
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def send_request(content)
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
def process_response(content)
|
36
|
+
response = parse_response content
|
37
|
+
if response.is_a?(::Array)
|
38
|
+
response.map { |res| handle_response res }
|
39
|
+
else
|
40
|
+
handle_response response
|
41
|
+
end
|
42
|
+
rescue Saorin::InvalidResponse => e
|
43
|
+
raise e
|
44
|
+
rescue => e
|
45
|
+
p e
|
46
|
+
print e.backtrace.join("\t\n")
|
47
|
+
raise Saorin::InvalidResponse, e.to_s
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_response(content)
|
51
|
+
MultiJson.decode content
|
52
|
+
rescue MultiJson::LoadError => e
|
53
|
+
raise Saorin::InvalidResponse, e.to_s
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_content(response)
|
57
|
+
return nil if response.nil?
|
58
|
+
if response.error?
|
59
|
+
code, message, data = response.error.values_at('code', 'message', 'data')
|
60
|
+
error_class = Saorin.code_to_error code
|
61
|
+
raise Error, 'unknown error code' unless error_class
|
62
|
+
error_class.new message, :code => code, :data => data
|
63
|
+
else
|
64
|
+
response.result
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def handle_response(hash)
|
69
|
+
return nil if hash.nil?
|
70
|
+
response = Response.from_hash(hash)
|
71
|
+
response.validate
|
72
|
+
to_content response
|
73
|
+
end
|
74
|
+
|
75
|
+
def seqid
|
76
|
+
@@seqid ||= 0
|
77
|
+
end
|
78
|
+
|
79
|
+
def seqid=(value)
|
80
|
+
@@seqid = value
|
81
|
+
@@seqid = 0 if @@seqid >= (1 << 31)
|
82
|
+
@@seqid
|
83
|
+
end
|
84
|
+
|
85
|
+
def seqid!
|
86
|
+
id = self.seqid
|
87
|
+
self.seqid += 1
|
88
|
+
id
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'saorin/client/base'
|
2
|
+
require 'faraday'
|
3
|
+
|
4
|
+
module Saorin
|
5
|
+
module Client
|
6
|
+
class Faraday
|
7
|
+
include Base
|
8
|
+
|
9
|
+
attr_reader :connection
|
10
|
+
|
11
|
+
def initialize(options = {}, &block)
|
12
|
+
super options
|
13
|
+
|
14
|
+
@connection = ::Faraday::Connection.new(options) do |builder|
|
15
|
+
builder.adapter ::Faraday.default_adapter
|
16
|
+
builder.response :raise_error
|
17
|
+
block.call builder if block
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_request(content)
|
22
|
+
response = @connection.post do |req|
|
23
|
+
req.headers[:content_type] = CONTENT_TYPE
|
24
|
+
req.body = content
|
25
|
+
end
|
26
|
+
response.body
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
register :faraday, Faraday
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'saorin/error'
|
2
|
+
|
3
|
+
module Saorin
|
4
|
+
module Registerable
|
5
|
+
class << self
|
6
|
+
def included(base)
|
7
|
+
base.extend ClassMethods
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
attr_accessor :load_path
|
13
|
+
|
14
|
+
def adapters
|
15
|
+
@adapters ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def register(key, adapter)
|
19
|
+
adapters[key.to_s] = adapter
|
20
|
+
end
|
21
|
+
|
22
|
+
def guess(key)
|
23
|
+
key = key.to_s
|
24
|
+
require "#{load_path}/#{key}"
|
25
|
+
adapter = adapters[key]
|
26
|
+
raise AdapterNotFound, key unless adapter
|
27
|
+
adapter
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/saorin/server.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
require 'saorin/
|
1
|
+
require 'saorin/registerable'
|
2
2
|
|
3
3
|
module Saorin
|
4
|
-
|
4
|
+
module Server
|
5
|
+
include Registerable
|
6
|
+
self.load_path = 'saorin/server'
|
7
|
+
|
5
8
|
class << self
|
6
9
|
def new(handler, options = {}, &block)
|
7
10
|
adapter = options.delete(:adapter) || :rack
|
8
|
-
adapter_class =
|
11
|
+
adapter_class = guess adapter
|
9
12
|
adapter_class.new handler, options, &block
|
10
13
|
end
|
11
|
-
|
12
14
|
alias_method :start, :new
|
13
15
|
end
|
14
16
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'saorin/error'
|
2
|
+
require 'saorin/request'
|
3
|
+
require 'saorin/response'
|
4
|
+
require 'saorin/server'
|
5
|
+
|
6
|
+
module Saorin
|
7
|
+
module Server
|
8
|
+
module Base
|
9
|
+
attr_reader :handler, :allowed_methods
|
10
|
+
|
11
|
+
def initialize(handler, options = {})
|
12
|
+
@handler = handler
|
13
|
+
@allowed_methods = options[:allowed_methods] || handler.public_methods(false)
|
14
|
+
@allowed_methods.map! { |m| m.to_s }
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_request(content)
|
18
|
+
response = begin
|
19
|
+
request = parse_request content
|
20
|
+
if request.is_a?(::Array)
|
21
|
+
raise Saorin::InvalidRequest if request.empty?
|
22
|
+
responses = request.map { |req| handle_request(req) }
|
23
|
+
responses.compact!
|
24
|
+
responses.empty? ? nil : responses
|
25
|
+
else
|
26
|
+
handle_request(request)
|
27
|
+
end
|
28
|
+
rescue Saorin::Error => e
|
29
|
+
Response.new(:error => e)
|
30
|
+
end
|
31
|
+
|
32
|
+
response && MultiJson.dump(response)
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_request(content)
|
36
|
+
MultiJson.decode content
|
37
|
+
rescue MultiJson::LoadError
|
38
|
+
raise Saorin::ParseError
|
39
|
+
end
|
40
|
+
|
41
|
+
def handle_request(hash)
|
42
|
+
begin
|
43
|
+
request = Request.from_hash(hash)
|
44
|
+
request.validate
|
45
|
+
dispatch_request_with_trap_notification request
|
46
|
+
rescue Saorin::InvalidRequest => e
|
47
|
+
Response.new(:error => e)
|
48
|
+
rescue Saorin::Error => e
|
49
|
+
Response.new(:error => e, :id => request.id)
|
50
|
+
rescue Exception => e
|
51
|
+
options = {:error => Saorin::InternalError.new}
|
52
|
+
options[:id] = request.id if request
|
53
|
+
Response.new(options)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def dispatch_request_with_trap_notification(request)
|
58
|
+
result = dispatch_request request
|
59
|
+
Response.new(:result => result, :id => request.id)
|
60
|
+
ensure
|
61
|
+
return nil if request.notify?
|
62
|
+
end
|
63
|
+
|
64
|
+
def dispatch_request(request)
|
65
|
+
method = request.method.to_s
|
66
|
+
params = request.params || []
|
67
|
+
|
68
|
+
unless @allowed_methods.include?(method) && @handler.respond_to?(method)
|
69
|
+
raise Saorin::MethodNotFound
|
70
|
+
end
|
71
|
+
|
72
|
+
begin
|
73
|
+
if params.is_a?(::Hash)
|
74
|
+
@handler.__send__ method, params
|
75
|
+
else
|
76
|
+
@handler.__send__ method, *params
|
77
|
+
end
|
78
|
+
rescue ArgumentError
|
79
|
+
raise Saorin::InvalidParams
|
80
|
+
rescue Exception => e
|
81
|
+
raise Saorin::ServerError, e
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'saorin/server/base'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module Saorin
|
5
|
+
module Server
|
6
|
+
class Rack
|
7
|
+
include Base
|
8
|
+
|
9
|
+
DEFAULT_HEADERS = {
|
10
|
+
'Content-Type' => 'application/json'
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
def initialize(handler, options = {}, &block)
|
14
|
+
super handler, options
|
15
|
+
|
16
|
+
::Rack::Server.start({
|
17
|
+
:app => self,
|
18
|
+
:Host => options[:host],
|
19
|
+
:Port => options[:port],
|
20
|
+
}.merge(options))
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(env)
|
24
|
+
request = ::Rack::Request.new(env)
|
25
|
+
response = ::Rack::Response.new([], 200, DEFAULT_HEADERS.dup)
|
26
|
+
response.write process_request(request.body.read) if request.post?
|
27
|
+
response.finish
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
register :rack, Rack
|
32
|
+
end
|
33
|
+
end
|
data/lib/saorin/version.rb
CHANGED
data/saorin.gemspec
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'saorin/
|
2
|
+
require 'saorin/server/base'
|
3
3
|
|
4
|
-
describe Saorin::
|
4
|
+
describe Saorin::Server::Base do
|
5
5
|
it_should_behave_like 'rpc call' do
|
6
6
|
let(:process) do
|
7
7
|
handler = Saorin::Test::Handler.new
|
8
|
-
|
8
|
+
class VanillaServer
|
9
|
+
include Saorin::Server::Base
|
10
|
+
end
|
11
|
+
server = VanillaServer.new handler
|
9
12
|
proc do |input|
|
10
13
|
server.process_request input
|
11
14
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saorin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
@@ -75,22 +75,6 @@ dependencies:
|
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: reel
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '0'
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0'
|
94
78
|
- !ruby/object:Gem::Dependency
|
95
79
|
name: faraday
|
96
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,30 +105,24 @@ files:
|
|
121
105
|
- README.md
|
122
106
|
- Rakefile
|
123
107
|
- lib/saorin.rb
|
124
|
-
- lib/saorin/adapters.rb
|
125
|
-
- lib/saorin/adapters/clients.rb
|
126
|
-
- lib/saorin/adapters/clients/base.rb
|
127
|
-
- lib/saorin/adapters/clients/faraday.rb
|
128
|
-
- lib/saorin/adapters/registerable.rb
|
129
|
-
- lib/saorin/adapters/servers.rb
|
130
|
-
- lib/saorin/adapters/servers/base.rb
|
131
|
-
- lib/saorin/adapters/servers/rack.rb
|
132
|
-
- lib/saorin/adapters/servers/reel.rb
|
133
108
|
- lib/saorin/client.rb
|
109
|
+
- lib/saorin/client/base.rb
|
110
|
+
- lib/saorin/client/faraday.rb
|
134
111
|
- lib/saorin/error.rb
|
112
|
+
- lib/saorin/registerable.rb
|
135
113
|
- lib/saorin/request.rb
|
136
114
|
- lib/saorin/response.rb
|
137
115
|
- lib/saorin/server.rb
|
116
|
+
- lib/saorin/server/base.rb
|
117
|
+
- lib/saorin/server/rack.rb
|
138
118
|
- lib/saorin/test.rb
|
139
119
|
- lib/saorin/utility.rb
|
140
120
|
- lib/saorin/version.rb
|
141
121
|
- saorin.gemspec
|
142
|
-
- server.rb
|
143
|
-
- spec/adapter/base_spec.rb
|
144
|
-
- spec/adapter/servers/rack_spec.rb
|
145
|
-
- spec/adapter/servers/reel_spec.rb
|
146
122
|
- spec/request_spec.rb
|
147
123
|
- spec/response_spec.rb
|
124
|
+
- spec/server/base_spec.rb
|
125
|
+
- spec/server/rack_spec.rb
|
148
126
|
- spec/spec_helper.rb
|
149
127
|
- spec/support/rpc_call.rb
|
150
128
|
- spec/support/utils.rb
|
@@ -162,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
140
|
version: '0'
|
163
141
|
segments:
|
164
142
|
- 0
|
165
|
-
hash:
|
143
|
+
hash: 926844584898114179
|
166
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
145
|
none: false
|
168
146
|
requirements:
|
@@ -171,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
149
|
version: '0'
|
172
150
|
segments:
|
173
151
|
- 0
|
174
|
-
hash:
|
152
|
+
hash: 926844584898114179
|
175
153
|
requirements: []
|
176
154
|
rubyforge_project:
|
177
155
|
rubygems_version: 1.8.24
|
@@ -179,11 +157,10 @@ signing_key:
|
|
179
157
|
specification_version: 3
|
180
158
|
summary: JSON-RPC 2.0 server and client implementation for any protocols
|
181
159
|
test_files:
|
182
|
-
- spec/adapter/base_spec.rb
|
183
|
-
- spec/adapter/servers/rack_spec.rb
|
184
|
-
- spec/adapter/servers/reel_spec.rb
|
185
160
|
- spec/request_spec.rb
|
186
161
|
- spec/response_spec.rb
|
162
|
+
- spec/server/base_spec.rb
|
163
|
+
- spec/server/rack_spec.rb
|
187
164
|
- spec/spec_helper.rb
|
188
165
|
- spec/support/rpc_call.rb
|
189
166
|
- spec/support/utils.rb
|
data/lib/saorin/adapters.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
require 'saorin/request'
|
3
|
-
require 'saorin/response'
|
4
|
-
require 'saorin/adapters/clients'
|
5
|
-
|
6
|
-
module Saorin
|
7
|
-
module Adapters
|
8
|
-
module Clients
|
9
|
-
class Base
|
10
|
-
CONTENT_TYPE = 'application/json'.freeze
|
11
|
-
|
12
|
-
def initialize(options = {})
|
13
|
-
end
|
14
|
-
|
15
|
-
def call(method, *args)
|
16
|
-
apply Saorin::Request.new(method, args, :id => seqid!)
|
17
|
-
end
|
18
|
-
|
19
|
-
def notify(method, *args)
|
20
|
-
apply Saorin::Request.new(method, args)
|
21
|
-
end
|
22
|
-
|
23
|
-
def apply(request)
|
24
|
-
response = send_request request.to_json
|
25
|
-
content = process_response response
|
26
|
-
raise content if content.is_a?(Saorin::RPCError)
|
27
|
-
content
|
28
|
-
end
|
29
|
-
|
30
|
-
protected
|
31
|
-
|
32
|
-
def send_request(content)
|
33
|
-
raise NotImplementedError
|
34
|
-
end
|
35
|
-
|
36
|
-
def process_response(content)
|
37
|
-
response = parse_response content
|
38
|
-
if response.is_a?(::Array)
|
39
|
-
response.map { |res| handle_response res }
|
40
|
-
else
|
41
|
-
handle_response response
|
42
|
-
end
|
43
|
-
rescue Saorin::InvalidResponse => e
|
44
|
-
raise e
|
45
|
-
rescue => e
|
46
|
-
p e
|
47
|
-
print e.backtrace.join("\t\n")
|
48
|
-
raise Saorin::InvalidResponse, e.to_s
|
49
|
-
end
|
50
|
-
|
51
|
-
def parse_response(content)
|
52
|
-
MultiJson.decode content
|
53
|
-
rescue MultiJson::LoadError => e
|
54
|
-
raise Saorin::InvalidResponse, e.to_s
|
55
|
-
end
|
56
|
-
|
57
|
-
def to_content(response)
|
58
|
-
return nil if response.nil?
|
59
|
-
if response.error?
|
60
|
-
code, message, data = response.error.values_at('code', 'message', 'data')
|
61
|
-
error_class = Saorin.code_to_error code
|
62
|
-
raise Error, 'unknown error code' unless error_class
|
63
|
-
error_class.new message, :code => code, :data => data
|
64
|
-
else
|
65
|
-
response.result
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def handle_response(hash)
|
70
|
-
return nil if hash.nil?
|
71
|
-
response = Response.from_hash(hash)
|
72
|
-
response.validate
|
73
|
-
to_content response
|
74
|
-
end
|
75
|
-
|
76
|
-
def seqid
|
77
|
-
@@seqid ||= 0
|
78
|
-
end
|
79
|
-
|
80
|
-
def seqid=(value)
|
81
|
-
@@seqid = value
|
82
|
-
@@seqid = 0 if @@seqid >= (1 << 31)
|
83
|
-
@@seqid
|
84
|
-
end
|
85
|
-
|
86
|
-
def seqid!
|
87
|
-
id = self.seqid
|
88
|
-
self.seqid += 1
|
89
|
-
id
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'saorin/adapters/clients/base'
|
2
|
-
require 'faraday'
|
3
|
-
|
4
|
-
module Saorin
|
5
|
-
module Adapters
|
6
|
-
module Clients
|
7
|
-
class Faraday < Base
|
8
|
-
attr_reader :connection
|
9
|
-
|
10
|
-
def initialize(options = {}, &block)
|
11
|
-
super options
|
12
|
-
|
13
|
-
@connection = ::Faraday::Connection.new(options) do |builder|
|
14
|
-
builder.adapter ::Faraday.default_adapter
|
15
|
-
builder.response :raise_error
|
16
|
-
block.call builder if block
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def send_request(content)
|
21
|
-
response = @connection.post do |req|
|
22
|
-
req.headers[:content_type] = CONTENT_TYPE
|
23
|
-
req.body = content
|
24
|
-
end
|
25
|
-
response.body
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
register :faraday, Faraday
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'saorin/error'
|
2
|
-
|
3
|
-
module Saorin
|
4
|
-
module Adapters
|
5
|
-
module Registerable
|
6
|
-
class << self
|
7
|
-
def included(base)
|
8
|
-
base.extend ClassMethods
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
attr_accessor :load_path
|
14
|
-
|
15
|
-
def adapters
|
16
|
-
@adapters ||= {}
|
17
|
-
end
|
18
|
-
|
19
|
-
def register(key, adapter)
|
20
|
-
adapters[key.to_s] = adapter
|
21
|
-
end
|
22
|
-
|
23
|
-
def guess(key)
|
24
|
-
key = key.to_s
|
25
|
-
require "#{load_path}/#{key}"
|
26
|
-
adapter = adapters[key]
|
27
|
-
raise AdapterNotFound, key unless adapter
|
28
|
-
adapter
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,88 +0,0 @@
|
|
1
|
-
require 'saorin/error'
|
2
|
-
require 'saorin/request'
|
3
|
-
require 'saorin/response'
|
4
|
-
require 'saorin/adapters/servers'
|
5
|
-
|
6
|
-
module Saorin
|
7
|
-
module Adapters
|
8
|
-
module Servers
|
9
|
-
class Base
|
10
|
-
attr_reader :handler, :allowed_methods
|
11
|
-
|
12
|
-
def initialize(handler, options = {})
|
13
|
-
@handler = handler
|
14
|
-
@allowed_methods = options[:allowed_methods] || handler.public_methods(false)
|
15
|
-
@allowed_methods.map! { |m| m.to_s }
|
16
|
-
end
|
17
|
-
|
18
|
-
def process_request(content)
|
19
|
-
response = begin
|
20
|
-
request = parse_request content
|
21
|
-
if request.is_a?(::Array)
|
22
|
-
raise Saorin::InvalidRequest if request.empty?
|
23
|
-
responses = request.map { |req| handle_request(req) }
|
24
|
-
responses.compact!
|
25
|
-
responses.empty? ? nil : responses
|
26
|
-
else
|
27
|
-
handle_request(request)
|
28
|
-
end
|
29
|
-
rescue Saorin::Error => e
|
30
|
-
Response.new(:error => e)
|
31
|
-
end
|
32
|
-
|
33
|
-
response && MultiJson.dump(response)
|
34
|
-
end
|
35
|
-
|
36
|
-
def parse_request(content)
|
37
|
-
MultiJson.decode content
|
38
|
-
rescue MultiJson::LoadError
|
39
|
-
raise Saorin::ParseError
|
40
|
-
end
|
41
|
-
|
42
|
-
def handle_request(hash)
|
43
|
-
begin
|
44
|
-
request = Request.from_hash(hash)
|
45
|
-
request.validate
|
46
|
-
dispatch_request_with_trap_notification request
|
47
|
-
rescue Saorin::InvalidRequest => e
|
48
|
-
Response.new(:error => e)
|
49
|
-
rescue Saorin::Error => e
|
50
|
-
Response.new(:error => e, :id => request.id)
|
51
|
-
rescue Exception => e
|
52
|
-
options = {:error => Saorin::InternalError.new}
|
53
|
-
options[:id] = request.id if request
|
54
|
-
Response.new(options)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def dispatch_request_with_trap_notification(request)
|
59
|
-
result = dispatch_request request
|
60
|
-
Response.new(:result => result, :id => request.id)
|
61
|
-
ensure
|
62
|
-
return nil if request.notify?
|
63
|
-
end
|
64
|
-
|
65
|
-
def dispatch_request(request)
|
66
|
-
method = request.method.to_s
|
67
|
-
params = request.params || []
|
68
|
-
|
69
|
-
unless @allowed_methods.include?(method) && @handler.respond_to?(method)
|
70
|
-
raise Saorin::MethodNotFound
|
71
|
-
end
|
72
|
-
|
73
|
-
begin
|
74
|
-
if params.is_a?(::Hash)
|
75
|
-
@handler.__send__ method, params
|
76
|
-
else
|
77
|
-
@handler.__send__ method, *params
|
78
|
-
end
|
79
|
-
rescue ArgumentError
|
80
|
-
raise Saorin::InvalidParams
|
81
|
-
rescue Exception => e
|
82
|
-
raise Saorin::ServerError, e
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'saorin/adapters/servers/base'
|
2
|
-
require 'rack'
|
3
|
-
|
4
|
-
module Saorin
|
5
|
-
module Adapters
|
6
|
-
module Servers
|
7
|
-
class Rack < Base
|
8
|
-
DEFAULT_HEADERS = {
|
9
|
-
'Content-Type' => 'application/json'
|
10
|
-
}.freeze
|
11
|
-
|
12
|
-
def initialize(handler, options = {}, &block)
|
13
|
-
super handler, options
|
14
|
-
|
15
|
-
::Rack::Server.start({
|
16
|
-
:app => self,
|
17
|
-
:Host => options[:host],
|
18
|
-
:Port => options[:port],
|
19
|
-
}.merge(options))
|
20
|
-
end
|
21
|
-
|
22
|
-
def call(env)
|
23
|
-
request = ::Rack::Request.new(env)
|
24
|
-
response = ::Rack::Response.new([], 200, DEFAULT_HEADERS.dup)
|
25
|
-
response.write process_request(request.body.read) if request.post?
|
26
|
-
response.finish
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
register :rack, Rack
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'saorin/adapters/servers/base'
|
2
|
-
require 'reel'
|
3
|
-
|
4
|
-
module Saorin
|
5
|
-
module Adapters
|
6
|
-
module Servers
|
7
|
-
class Reel < Base
|
8
|
-
DEFAULT_HEADERS = {
|
9
|
-
'Content-Type' => 'application/json'
|
10
|
-
}.freeze
|
11
|
-
|
12
|
-
attr_reader :server
|
13
|
-
|
14
|
-
def initialize(handler, options = {}, &block)
|
15
|
-
super handler, options
|
16
|
-
|
17
|
-
@server = ::Reel::Server.supervise(options[:host], options[:port], &method(:process))
|
18
|
-
trap(:INT) { @server.terminate; exit }
|
19
|
-
sleep unless options[:nonblock]
|
20
|
-
end
|
21
|
-
|
22
|
-
def process(connection)
|
23
|
-
while request = connection.request
|
24
|
-
case request
|
25
|
-
when ::Reel::Request
|
26
|
-
response_body = process_request(request.body) if request.method.to_s.upcase == 'POST'
|
27
|
-
response_body ||= ''
|
28
|
-
request.respond :ok, DEFAULT_HEADERS.dup, response_body
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
register :reel, Reel
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/server.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# -*- encoding: utf-8 -*-
|
3
|
-
require 'saorin'
|
4
|
-
|
5
|
-
class Handler
|
6
|
-
def log(tag, time, record)
|
7
|
-
p [tag, time, record]
|
8
|
-
nil
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
Saorin::Server.start Handler.new, :host => 'localhost', :port => 25252, :adapter => :reel
|
13
|
-
|
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'saorin/test'
|
3
|
-
require 'saorin/adapters/servers/reel'
|
4
|
-
|
5
|
-
describe Saorin::Adapters::Servers::Reel do
|
6
|
-
include Saorin::Test
|
7
|
-
|
8
|
-
let(:server_adapter) { :reel }
|
9
|
-
include_context 'setup rpc server client'
|
10
|
-
it_should_behave_like 'rpc server client'
|
11
|
-
end
|