jimson 0.3.0 → 0.3.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/CHANGELOG.rdoc +6 -0
- data/VERSION +1 -1
- data/lib/jimson/server.rb +131 -4
- metadata +7 -8
- data/lib/jimson/http_server.rb +0 -138
data/CHANGELOG.rdoc
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.1
|
data/lib/jimson/server.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'rack'
|
2
2
|
require 'rack/request'
|
3
3
|
require 'rack/response'
|
4
|
-
require 'rack/showexceptions'
|
5
4
|
require 'json'
|
6
|
-
require 'jimson/http_server'
|
7
5
|
|
8
6
|
module Jimson
|
9
7
|
class Server
|
10
8
|
|
9
|
+
JSON_RPC_VERSION = '2.0'
|
10
|
+
|
11
11
|
attr_accessor :handler, :host, :port
|
12
12
|
|
13
13
|
#
|
@@ -20,7 +20,6 @@ module Jimson
|
|
20
20
|
#
|
21
21
|
def initialize(handler, opts = {})
|
22
22
|
@handler = handler
|
23
|
-
@app = Jimson::HttpServer.new(@handler)
|
24
23
|
@host = opts[:host] || '0.0.0.0'
|
25
24
|
@port = opts[:port] || 8999
|
26
25
|
@server = opts[:server] || 'webrick'
|
@@ -32,11 +31,139 @@ module Jimson
|
|
32
31
|
def start
|
33
32
|
Rack::Server.start(
|
34
33
|
:server => @server,
|
35
|
-
:app =>
|
34
|
+
:app => self,
|
36
35
|
:Host => @host,
|
37
36
|
:Port => @port
|
38
37
|
)
|
39
38
|
end
|
40
39
|
|
40
|
+
#
|
41
|
+
# Entry point for Rack
|
42
|
+
#
|
43
|
+
def call(env)
|
44
|
+
req = Rack::Request.new(env)
|
45
|
+
resp = Rack::Response.new
|
46
|
+
return resp.finish if !req.post?
|
47
|
+
resp.write process(req.body.read)
|
48
|
+
resp.finish
|
49
|
+
end
|
50
|
+
|
51
|
+
def process(content)
|
52
|
+
begin
|
53
|
+
request = parse_request(content)
|
54
|
+
if request.is_a?(Array)
|
55
|
+
raise Jimson::ServerError::InvalidRequest.new if request.empty?
|
56
|
+
response = request.map { |req| handle_request(req) }
|
57
|
+
else
|
58
|
+
response = handle_request(request)
|
59
|
+
end
|
60
|
+
rescue Jimson::ServerError::ParseError, Jimson::ServerError::InvalidRequest => e
|
61
|
+
response = error_response(e)
|
62
|
+
rescue Jimson::ServerError::Generic => e
|
63
|
+
response = error_response(e, request)
|
64
|
+
rescue StandardError, Exception
|
65
|
+
response = error_response(Jimson::ServerError::InternalError.new)
|
66
|
+
end
|
67
|
+
|
68
|
+
response.compact! if response.is_a?(Array)
|
69
|
+
|
70
|
+
return nil if response.nil? || (response.respond_to?(:empty?) && response.empty?)
|
71
|
+
|
72
|
+
response.to_json
|
73
|
+
end
|
74
|
+
|
75
|
+
def handle_request(request)
|
76
|
+
response = nil
|
77
|
+
begin
|
78
|
+
if !validate_request(request)
|
79
|
+
response = error_response(Jimson::ServerError::InvalidRequest.new)
|
80
|
+
else
|
81
|
+
response = create_response(request)
|
82
|
+
end
|
83
|
+
rescue Jimson::ServerError::Generic => e
|
84
|
+
response = error_response(e, request)
|
85
|
+
end
|
86
|
+
|
87
|
+
response
|
88
|
+
end
|
89
|
+
|
90
|
+
def validate_request(request)
|
91
|
+
required_keys = %w(jsonrpc method)
|
92
|
+
required_types = {
|
93
|
+
'jsonrpc' => [String],
|
94
|
+
'method' => [String],
|
95
|
+
'params' => [Hash, Array],
|
96
|
+
'id' => [String, Fixnum, NilClass]
|
97
|
+
}
|
98
|
+
|
99
|
+
return false if !request.is_a?(Hash)
|
100
|
+
|
101
|
+
required_keys.each do |key|
|
102
|
+
return false if !request.has_key?(key)
|
103
|
+
end
|
104
|
+
|
105
|
+
required_types.each do |key, types|
|
106
|
+
return false if request.has_key?(key) && !types.any? { |type| request[key].is_a?(type) }
|
107
|
+
end
|
108
|
+
|
109
|
+
return false if request['jsonrpc'] != JSON_RPC_VERSION
|
110
|
+
|
111
|
+
true
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_response(request)
|
115
|
+
params = request['params']
|
116
|
+
begin
|
117
|
+
if params.is_a?(Hash)
|
118
|
+
result = @handler.send(request['method'], params)
|
119
|
+
else
|
120
|
+
result = @handler.send(request['method'], *params)
|
121
|
+
end
|
122
|
+
rescue NoMethodError
|
123
|
+
raise Jimson::ServerError::MethodNotFound.new
|
124
|
+
rescue ArgumentError
|
125
|
+
raise Jimson::ServerError::InvalidParams.new
|
126
|
+
rescue
|
127
|
+
raise Jimson::ServerError::ApplicationError.new($!)
|
128
|
+
end
|
129
|
+
|
130
|
+
response = success_response(request, result)
|
131
|
+
|
132
|
+
# A Notification is a Request object without an "id" member.
|
133
|
+
# The Server MUST NOT reply to a Notification, including those
|
134
|
+
# that are within a batch request.
|
135
|
+
response = nil if !request.has_key?('id')
|
136
|
+
|
137
|
+
response
|
138
|
+
end
|
139
|
+
|
140
|
+
def error_response(error, request = nil)
|
141
|
+
resp = {
|
142
|
+
'jsonrpc' => JSON_RPC_VERSION,
|
143
|
+
'error' => error.to_h,
|
144
|
+
}
|
145
|
+
if !!request && request.has_key?('id')
|
146
|
+
resp['id'] = request['id']
|
147
|
+
else
|
148
|
+
resp['id'] = nil
|
149
|
+
end
|
150
|
+
|
151
|
+
resp
|
152
|
+
end
|
153
|
+
|
154
|
+
def success_response(request, result)
|
155
|
+
{
|
156
|
+
'jsonrpc' => JSON_RPC_VERSION,
|
157
|
+
'result' => result,
|
158
|
+
'id' => request['id']
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
def parse_request(post)
|
163
|
+
data = JSON.parse(post)
|
164
|
+
rescue
|
165
|
+
raise Jimson::ServerError::ParseError.new
|
166
|
+
end
|
167
|
+
|
41
168
|
end
|
42
169
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jimson
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-08-11 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|
16
|
-
requirement: &
|
16
|
+
requirement: &12229180 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.6.3
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *12229180
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: json
|
27
|
-
requirement: &
|
27
|
+
requirement: &12228700 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.5.1
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *12228700
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rack
|
38
|
-
requirement: &
|
38
|
+
requirement: &12225120 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '1.3'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *12225120
|
47
47
|
description:
|
48
48
|
email:
|
49
49
|
executables: []
|
@@ -62,7 +62,6 @@ files:
|
|
62
62
|
- lib/jimson/server_error.rb
|
63
63
|
- lib/jimson/response.rb
|
64
64
|
- lib/jimson/request.rb
|
65
|
-
- lib/jimson/http_server.rb
|
66
65
|
- lib/jimson/client.rb
|
67
66
|
- spec/server_spec.rb
|
68
67
|
- spec/client_spec.rb
|
data/lib/jimson/http_server.rb
DELETED
@@ -1,138 +0,0 @@
|
|
1
|
-
require 'jimson/server_error'
|
2
|
-
|
3
|
-
module Jimson
|
4
|
-
class HttpServer
|
5
|
-
|
6
|
-
JSON_RPC_VERSION = '2.0'
|
7
|
-
|
8
|
-
def initialize(handler)
|
9
|
-
@handler = handler
|
10
|
-
end
|
11
|
-
|
12
|
-
def call(env)
|
13
|
-
req = Rack::Request.new(env)
|
14
|
-
resp = Rack::Response.new
|
15
|
-
return resp.finish if !req.post?
|
16
|
-
resp.write process(req.body.read)
|
17
|
-
resp.finish
|
18
|
-
end
|
19
|
-
|
20
|
-
def process(content)
|
21
|
-
begin
|
22
|
-
request = parse_request(content)
|
23
|
-
if request.is_a?(Array)
|
24
|
-
raise Jimson::ServerError::InvalidRequest.new if request.empty?
|
25
|
-
response = request.map { |req| handle_request(req) }
|
26
|
-
else
|
27
|
-
response = handle_request(request)
|
28
|
-
end
|
29
|
-
rescue Jimson::ServerError::ParseError, Jimson::ServerError::InvalidRequest => e
|
30
|
-
response = error_response(e)
|
31
|
-
rescue Jimson::ServerError::Generic => e
|
32
|
-
response = error_response(e, request)
|
33
|
-
rescue StandardError, Exception
|
34
|
-
response = error_response(Jimson::ServerError::InternalError.new)
|
35
|
-
end
|
36
|
-
|
37
|
-
response.compact! if response.is_a?(Array)
|
38
|
-
|
39
|
-
return nil if response.nil? || (response.respond_to?(:empty?) && response.empty?)
|
40
|
-
|
41
|
-
response.to_json
|
42
|
-
end
|
43
|
-
|
44
|
-
def handle_request(request)
|
45
|
-
response = nil
|
46
|
-
begin
|
47
|
-
if !validate_request(request)
|
48
|
-
response = error_response(Jimson::ServerError::InvalidRequest.new)
|
49
|
-
else
|
50
|
-
response = create_response(request)
|
51
|
-
end
|
52
|
-
rescue Jimson::ServerError::Generic => e
|
53
|
-
response = error_response(e, request)
|
54
|
-
end
|
55
|
-
|
56
|
-
response
|
57
|
-
end
|
58
|
-
|
59
|
-
def validate_request(request)
|
60
|
-
required_keys = %w(jsonrpc method)
|
61
|
-
required_types = {
|
62
|
-
'jsonrpc' => [String],
|
63
|
-
'method' => [String],
|
64
|
-
'params' => [Hash, Array],
|
65
|
-
'id' => [String, Fixnum, NilClass]
|
66
|
-
}
|
67
|
-
|
68
|
-
return false if !request.is_a?(Hash)
|
69
|
-
|
70
|
-
required_keys.each do |key|
|
71
|
-
return false if !request.has_key?(key)
|
72
|
-
end
|
73
|
-
|
74
|
-
required_types.each do |key, types|
|
75
|
-
return false if request.has_key?(key) && !types.any? { |type| request[key].is_a?(type) }
|
76
|
-
end
|
77
|
-
|
78
|
-
return false if request['jsonrpc'] != JSON_RPC_VERSION
|
79
|
-
|
80
|
-
true
|
81
|
-
end
|
82
|
-
|
83
|
-
def create_response(request)
|
84
|
-
params = request['params']
|
85
|
-
begin
|
86
|
-
if params.is_a?(Hash)
|
87
|
-
result = @handler.send(request['method'], params)
|
88
|
-
else
|
89
|
-
result = @handler.send(request['method'], *params)
|
90
|
-
end
|
91
|
-
rescue NoMethodError
|
92
|
-
raise Jimson::ServerError::MethodNotFound.new
|
93
|
-
rescue ArgumentError
|
94
|
-
raise Jimson::ServerError::InvalidParams.new
|
95
|
-
rescue
|
96
|
-
raise Jimson::ServerError::ApplicationError.new($!)
|
97
|
-
end
|
98
|
-
|
99
|
-
response = success_response(request, result)
|
100
|
-
|
101
|
-
# A Notification is a Request object without an "id" member.
|
102
|
-
# The Server MUST NOT reply to a Notification, including those
|
103
|
-
# that are within a batch request.
|
104
|
-
response = nil if !request.has_key?('id')
|
105
|
-
|
106
|
-
response
|
107
|
-
end
|
108
|
-
|
109
|
-
def error_response(error, request = nil)
|
110
|
-
resp = {
|
111
|
-
'jsonrpc' => JSON_RPC_VERSION,
|
112
|
-
'error' => error.to_h,
|
113
|
-
}
|
114
|
-
if !!request && request.has_key?('id')
|
115
|
-
resp['id'] = request['id']
|
116
|
-
else
|
117
|
-
resp['id'] = nil
|
118
|
-
end
|
119
|
-
|
120
|
-
resp
|
121
|
-
end
|
122
|
-
|
123
|
-
def success_response(request, result)
|
124
|
-
{
|
125
|
-
'jsonrpc' => JSON_RPC_VERSION,
|
126
|
-
'result' => result,
|
127
|
-
'id' => request['id']
|
128
|
-
}
|
129
|
-
end
|
130
|
-
|
131
|
-
def parse_request(post)
|
132
|
-
data = JSON.parse(post)
|
133
|
-
rescue
|
134
|
-
raise Jimson::ServerError::ParseError.new
|
135
|
-
end
|
136
|
-
|
137
|
-
end
|
138
|
-
end
|