jsonrpc-server 0.1.1 → 0.2.0

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.
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