jsonrpc-server 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README +35 -0
  2. data/lib/json_server.rb +92 -52
  3. metadata +6 -5
data/README ADDED
@@ -0,0 +1,35 @@
1
+ == About
2
+
3
+ This is an implementation of {JSON RPC 2.0}[link:http://groups.google.com/group/json-rpc/web/json-rpc-2-0?pli=1] server
4
+
5
+ == Using
6
+
7
+ To make your rails controller JSON RPC 2.0 callable, make next include:
8
+
9
+ class TestController < ActionController::Base
10
+ include JSONServer
11
+
12
+ def summ(left, right)
13
+ return left+right
14
+ end
15
+ end
16
+
17
+ In your config/routing.rb you will have to add
18
+
19
+ post 'json' => 'test#index'
20
+
21
+ JSONServer will automaticaly check if posted json is valid JSON-RPC 2.0 request
22
+ and and fire called method. if method is not found - propper error will be sent.
23
+
24
+ Batch request are handled.
25
+
26
+ == Errors
27
+
28
+ You can raise standart errors, or JSONServer::Error with parameters :code,
29
+ :message, :data, which will be set for correspoding fields
30
+ :code defaults to -30000 if JSONServer::Error and to -32000 otherwise
31
+ :message defaults to "Runtime Error"
32
+
33
+ == TODO list
34
+
35
+ write tests
data/lib/json_server.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'json'
2
+
1
3
  module JSONServer
2
4
 
3
- class Error < RuntimeError
5
+ @@JSONRPCVersion = "2.0".freeze
6
+
7
+ class JSONRPCError < RuntimeError
4
8
  attr_reader :code, :message, :data
5
9
  def initialize obj = {}
6
10
  @code = obj[:code] || -30000
@@ -9,87 +13,123 @@ module JSONServer
9
13
  end
10
14
  end
11
15
 
12
- def index
16
+ def dispatch_json_2 request
17
+ # here request specific errors are handled
13
18
  begin
14
- data = ActiveSupport::JSON.decode request.body
15
- rescue StandardError
16
- render :json => parseError
17
- return
19
+ # no wraping, because single_request dispatcher does it
20
+ result = core_dispatch request
21
+ rescue JSONRPCError
22
+ result = wrap_error({ :code => $!.code,
23
+ :message => $!.message,
24
+ :data => $!.data
25
+ })
26
+ rescue RuntimeError
27
+ result = wrap_error({ :code => -32000,
28
+ :message => $!.message,
29
+ :data => $!.to_s
30
+ })
18
31
  end
19
- if data.class == Array
20
- if data.length == 0
21
- render :json => invalidRequest
22
- return
23
- end
24
- res = data.collect { |single|
25
- parseSingle single
26
- }
27
- render :json => res
28
- return
32
+ if result != nil
33
+ return result.to_json
29
34
  end
30
- render :json => parseSingle(data)
35
+ return ''
31
36
  end
32
37
 
33
38
  private
34
39
 
35
- def parseSingle(data)
36
- if data.class != Hash ||
37
- data["jsonrpc"] != "2.0" ||
38
- data["method"].class != String ||
39
- data["method"] == ""
40
- return invalidRequest
40
+ def core_dispatch request
41
+ begin
42
+ data = JSON.parse request
43
+ rescue JSON::ParserError
44
+ parse_error # converting error into json-rpc 2.0
45
+ end
46
+ if data.kind_of? Array
47
+ invalid_request if data.length == 0 # batch can not be empty
48
+ res = data.collect{ |single|
49
+ parse_single single
50
+ }
51
+ res.delete(nil)
52
+ return res unless res.length == 0
53
+ return nil
41
54
  end
42
- result = { :jsonrpc => "2.0", :id => data["id"] }
55
+ parse_single data
56
+ end
57
+
58
+ def wrap data, id = nil
59
+ data.update({ :jsonrpc => @@JSONRPCVersion, :id => id })
60
+ end
61
+
62
+ def wrap_error error, id = nil
63
+ wrap({ :error => error }, id)
64
+ end
65
+
66
+ def wrap_result result, id = nil
67
+ wrap({:result => result}, id)
68
+ end
69
+
70
+ def parse_single(data)
71
+ current_id = nil
43
72
  begin
73
+ invalid_request unless data.kind_of?(Hash)
74
+ current_id = data["id"] unless data["id"] == nil
75
+ if data["jsonrpc"] != @@JSONRPCVersion ||
76
+ (not data["method"].kind_of?(String)) ||
77
+ data["method"] == ""
78
+ invalid_request
79
+ end
44
80
  self.class.public_instance_methods.each { |method|
45
81
  if method.to_s == data["method"]
46
- if data["params"].class == Array
82
+ if data["params"].kind_of? Array
47
83
  arr = data["params"]
48
84
  elsif
49
85
  arr = self.method(data["method"]).parameters.collect { |pd|
50
86
  data["params"][pd[1].to_s]
51
87
  }
52
88
  end
53
- result["result"] = self.send(data["method"], *arr)
54
- return result
89
+ result = self.send(data["method"], *arr)
90
+ if current_id != nil
91
+ return wrap_result(result, current_id)
92
+ else
93
+ return
94
+ end
55
95
  end
56
96
  }
57
- rescue Error
58
- result["code"] = $!.code
59
- result["message"] = $!.message
60
- result["data"] = $!.data
61
- return result
97
+ method_not_found
98
+ rescue JSONRPCError
99
+ result = wrap_error({ :code => $!.code,
100
+ :message => $!.message,
101
+ :data => $!.data
102
+ }, current_id)
62
103
  rescue RuntimeError
63
- result["code"] = -32000
64
- result["message"] = $!.message
65
- result["data"] = $!
66
- return result
104
+ result = wrap_error({ :code => -32000,
105
+ :message => $!.message,
106
+ :data => $!.to_s
107
+ }, current_id)
67
108
  end
68
- return methodNotFound data["id"]
69
109
  end
70
110
 
71
111
  ##
72
112
  # Error handling section
73
113
  ##
74
114
 
75
- def methodNotFound id
76
- return {:jsonrpc => "2.0",
77
- :error => {:code => -32601,
78
- :message => "Procedure not found."},
79
- :id => id}
115
+ def method_not_found
116
+ raise(JSONRPCError, {
117
+ :code => -32601,
118
+ :message => "Method not found."
119
+ }, caller)
80
120
  end
81
121
 
82
- def parseError
83
- return {:jsonrpc => "2.0",
84
- :error => {:code => -32700,
85
- :message => "Parse error."},
86
- :id => nil}
122
+ def parse_error
123
+ raise(JSONRPCError, {
124
+ :code => -32700,
125
+ :message => "Parse error."
126
+ }, caller)
87
127
  end
88
128
 
89
- def invalidRequest
90
- return {:jsonrpc => "2.0",
91
- :error => {:code => -32600,
92
- :message => "Invalid Request."},
93
- :id => nil}
129
+ def invalid_request
130
+ raise(JSONRPCError, {
131
+ :code => -32600,
132
+ :message => "Invalid Request."
133
+ }, caller)
94
134
  end
95
135
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 1
9
- version: 0.1.1
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Dima Levchenko
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-05-30 00:00:00 +03:00
17
+ date: 2011-05-31 00:00:00 +03:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -28,6 +28,7 @@ extra_rdoc_files: []
28
28
 
29
29
  files:
30
30
  - lib/json_server.rb
31
+ - README
31
32
  has_rdoc: true
32
33
  homepage: http://rubygems.org/gems/jsonrpc-server
33
34
  licenses: []
@@ -55,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
56
  version: "0"
56
57
  requirements: []
57
58
 
58
- rubyforge_project:
59
+ rubyforge_project: "[none]"
59
60
  rubygems_version: 1.3.7
60
61
  signing_key:
61
62
  specification_version: 3