jsonrpc2 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fb244988f3e6da4bd9e07cb696ae0527dc60c5ec
4
+ data.tar.gz: 8b378af79f04b2603d6ac7ad669918bb9e055962
5
+ SHA512:
6
+ metadata.gz: 8ec025d776da30ad4251511f1907cad21fe1dc76580a907113417fe7e658de63435ec67976b96488c02b41806ab794452e1aad695769cb60059fc9d6dc35ceb7
7
+ data.tar.gz: 0f7017e7d77711638377d340d7aae1a6355ddca9b40a0ec7e0218c16dd31bc33a364a7e07acdcf10b9a991c1465987bda927fae0c0cb90c245028ebeb38fc8f3
@@ -4,6 +4,9 @@ A Rack compatible, documenting JSON-RPC 2 DSL/server implementation for ruby.
4
4
 
5
5
  ## Changes
6
6
 
7
+ * 0.1.1 - 4-Jan-2013
8
+ Improve logging of exceptions / failure
9
+
7
10
  * 0.1.0 - 4-Jan-2013
8
11
  Turn on timing & logging of all requests
9
12
 
@@ -13,6 +13,7 @@ class ::Object::Calculator < JSONRPC2::Interface
13
13
  param 'b', 'Number', 'b'
14
14
  result 'Number', 'a * b'
15
15
  def mul
16
+ raise JSONRPC2::KnownError, [123, "Don't like negative numbers", params] if params['a'] < 0 or params['b'] < 0
16
17
  params['a'] * params['b']
17
18
  end
18
19
 
@@ -61,6 +61,7 @@ class Interface
61
61
  # @param [Hash] environment Rack environment hash
62
62
  # @return [Array<Fixnum, Hash<String,String>, Array<String>>] Rack-compatible response
63
63
  def call(environment)
64
+ environment['json.request-id'] = Digest::MD5.hexdigest("#{$host ||= Socket.gethostname}-#{$$}-#{Time.now.to_f}")[0,8]
64
65
  request = Rack::Request.new(environment)
65
66
  catch :rack_response do
66
67
  best = JSONRPC2::HTTPUtils.which(environment['HTTP_ACCEPT'], %w[text/html application/json-rpc application/json])
@@ -84,8 +85,8 @@ class Interface
84
85
  end
85
86
 
86
87
  rescue Exception => e
87
- if env['rack.logger'].respond_to?(:error)
88
- env['rack.logger'].error "#{e.class}: #{e.message} - #{e.backtrace * "\n "}"
88
+ if environment['rack.logger'].respond_to?(:error)
89
+ environment['rack.logger'].error "#{e.class}: #{e.message} - #{e.backtrace * "\n "}"
89
90
  end
90
91
  raise e.class, e.message, e.backtrace
91
92
  end
@@ -99,13 +100,13 @@ class Interface
99
100
  else
100
101
  auth = env["HTTP_AUTHORIZATION"]
101
102
  end
102
- env['rack.logger'].info("[#{Time.now.strftime('%d/%m/%Y %H:%M:%S')}] [JSON-RPC2] #{env['REQUEST_URI']} - Auth: #{auth}, Data: #{data.inspect}")
103
+ env['rack.logger'].info("[JSON-RPC2] #{env['json.request-id']} #{env['REQUEST_URI']} - Auth: #{auth}, Data: #{data.is_a?(String) ? data : data.inspect}")
103
104
  end
104
105
  t = Time.now.to_f
105
106
  return yield
106
107
  ensure
107
108
  if env['rack.logger'].respond_to?(:info)
108
- env['rack.logger'].info("[#{Time.now.strftime('%d/%m/%Y %H:%M:%S')}] [JSON-RPC2] Completed in #{'%.3f' % ((Time.now.to_f - t) * 1000)}ms")
109
+ env['rack.logger'].info("[JSON-RPC2] #{env['json.request-id']} Completed in #{'%.3f' % ((Time.now.to_f - t) * 1000)}ms#{ $! ? " - exception = #{$!.class}:#{$!.message}" : "" }")
109
110
  end
110
111
  end
111
112
 
@@ -133,12 +134,14 @@ class Interface
133
134
  # @param [Hash,Array] rpc_data Array of calls or Hash containing one call
134
135
  # @return [Hash,Array] Depends on input, but either a hash result or an array of results corresponding to calls.
135
136
  def dispatch(rpc_data)
136
- case rpc_data
137
+ result = case rpc_data
137
138
  when Array
138
- rpc_data.map { |rpc| dispatch_single(rpc) }.to_json
139
+ rpc_data.map { |rpc| dispatch_single(rpc) }
139
140
  else
140
- dispatch_single(rpc_data).to_json
141
+ dispatch_single(rpc_data)
141
142
  end
143
+
144
+ return result.to_json
142
145
  end
143
146
 
144
147
  protected
@@ -162,17 +165,32 @@ class Interface
162
165
  def request
163
166
  @_jsonrpc_request
164
167
  end
168
+ def env
169
+ @_jsonrpc_env
170
+ end
165
171
 
166
172
  # Logger
167
173
  def logger
168
- @_jsonrpc_logger ||= (request['rack.logger'] || Rack::NullLogger.new("null"))
174
+ @_jsonrpc_logger ||= (@_jsonrpc_env['rack.logger'] || Rack::NullLogger.new("null"))
169
175
  end
170
176
  # Check call validity and authentication & make a single method call
171
177
  #
172
178
  # @param [Hash] rpc JSON-RPC-2 call
173
179
  def dispatch_single(rpc)
174
180
  t = Time.now.to_f
175
- logger.info("[JSON-RPC2] Call #{rpc.inspect}\n")
181
+
182
+ result = _dispatch_single(rpc)
183
+
184
+ if result['result']
185
+ logger.info("[JSON-RPC2] #{env['json.request-id']} Call completed OK in #{'%.3f' % ((Time.now.to_f - t) * 1000)}ms")
186
+ elsif result['error']
187
+ logger.info("[JSON-RPC2] #{env['json.request-id']} Call to ##{rpc['method']} failed in #{'%.3f' % ((Time.now.to_f - t) * 1000)}ms with error #{result['error']['code']} - #{result['error']['message']}")
188
+ end
189
+
190
+ result
191
+ end
192
+ def _dispatch_single(rpc)
193
+ t = Time.now.to_f
176
194
  unless rpc.has_key?('id') && rpc.has_key?('method') && rpc['jsonrpc'].eql?('2.0')
177
195
  return response_error(-32600, 'Invalid request', nil)
178
196
  end
@@ -191,10 +209,10 @@ class Interface
191
209
  rescue KnownError => e
192
210
  response_error(e.code, e.message, e.data) # XXX: Change me
193
211
  rescue Exception => e
212
+ logger.error("#{env['json.request-id']} Internal error calling #{rpc.inspect} - #{e.class}: #{e.message} #{e.backtrace.join("\n ")}") if logger.respond_to?(:error)
194
213
  response_error(-32000, "#{e.class}: #{e.message}", e.backtrace) # XXX: Change me
214
+ else
195
215
  end
196
- ensure
197
- logger.info("[JSON-RPC2] Call completed in #{'%.3f' % ((Time.now.to_f - t) * 1000)}ms\n")
198
216
  end
199
217
  # List API methods
200
218
  #
@@ -1,5 +1,5 @@
1
1
  # JSONRPC2 namespace module
2
2
  module JSONRPC2
3
3
  # Version
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
metadata CHANGED
@@ -1,124 +1,92 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: jsonrpc2
3
- version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Geoff Youngs
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2014-01-04 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2014-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: httpclient
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
32
20
  type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: json
36
21
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
46
34
  type: :runtime
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
49
- name: RedCloth
50
35
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
52
- none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 3
57
- segments:
58
- - 0
59
- version: "0"
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: RedCloth
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
60
48
  type: :runtime
61
- version_requirements: *id003
62
- - !ruby/object:Gem::Dependency
63
- name: thor
64
49
  prerelease: false
65
- requirement: &id004 !ruby/object:Gem::Requirement
66
- none: false
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 3
71
- segments:
72
- - 0
73
- version: "0"
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
74
62
  type: :runtime
75
- version_requirements: *id004
76
- description: |+
77
- == Description
78
-
79
- A Rack compatible JSON-RPC2 server domain specific language (DSL) - allows JSONRPC APIs to be
80
- defined as mountable Rack applications with inline documentation, authentication and type checking.
81
-
82
- e.g.
83
-
84
- class Calculator < JSONRPC2::Interface
85
- title "JSON-RPC2 Calculator"
86
- introduction "This interface allows basic maths calculations via JSON-RPC2"
87
- auth_with JSONRPC2::BasicAuth.new({'user' => 'secretword'})
88
-
89
- section 'Simple Ops' do
90
- desc 'Multiply two numbers'
91
- param 'a', 'Number', 'a'
92
- param 'b', 'Number', 'b'
93
- result 'Number', 'a * b'
94
- def mul args
95
- args['a'] * args['b']
96
- end
97
-
98
- desc 'Add numbers'
99
- example "Calculate 1 + 1 = 2", :params => { 'a' => 1, 'b' => 1}, :result => 2
100
-
101
- param 'a', 'Number', 'First number'
102
- param 'b', 'Number', 'Second number'
103
- optional 'c', 'Number', 'Third number'
104
- result 'Number', 'a + b + c'
105
- def sum args
106
- val = args['a'] + args['b']
107
- val += args['c'] if args['c']
108
- val
109
- end
110
- end
111
- end
112
-
113
- email:
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: "== Description\n\nA Rack compatible JSON-RPC2 server domain specific
70
+ language (DSL) - allows JSONRPC APIs to be \ndefined as mountable Rack applications
71
+ with inline documentation, authentication and type checking.\n\ne.g.\n\n class
72
+ Calculator < JSONRPC2::Interface\n title \"JSON-RPC2 Calculator\"\n introduction
73
+ \"This interface allows basic maths calculations via JSON-RPC2\"\n auth_with
74
+ JSONRPC2::BasicAuth.new({'user' => 'secretword'})\n\n section 'Simple Ops' do\n
75
+ \ desc 'Multiply two numbers'\n param 'a', 'Number', 'a'\n param
76
+ 'b', 'Number', 'b'\n result 'Number', 'a * b'\n def mul args\n args['a']
77
+ * args['b']\n end\n\n desc 'Add numbers'\n example \"Calculate
78
+ 1 + 1 = 2\", :params => { 'a' => 1, 'b' => 1}, :result => 2\n\n param 'a',
79
+ 'Number', 'First number'\n param 'b', 'Number', 'Second number'\n optional
80
+ 'c', 'Number', 'Third number'\n result 'Number', 'a + b + c'\n def
81
+ sum args\n val = args['a'] + args['b']\n val += args['c'] if args['c']\n
82
+ \ val\n end\n end\n end\n\n"
83
+ email:
114
84
  - git@intersect-uk.co.uk
115
- executables:
85
+ executables:
116
86
  - jsonrpc2
117
87
  extensions: []
118
-
119
88
  extra_rdoc_files: []
120
-
121
- files:
89
+ files:
122
90
  - .gitignore
123
91
  - Gemfile
124
92
  - README.markdown
@@ -145,37 +113,25 @@ files:
145
113
  - test/test_types.rb
146
114
  homepage: http://github.com/geoffyoungs/jsonrpc2
147
115
  licenses: []
148
-
116
+ metadata: {}
149
117
  post_install_message:
150
118
  rdoc_options: []
151
-
152
- require_paths:
119
+ require_paths:
153
120
  - lib
154
- required_ruby_version: !ruby/object:Gem::Requirement
155
- none: false
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- hash: 3
160
- segments:
161
- - 0
162
- version: "0"
163
- required_rubygems_version: !ruby/object:Gem::Requirement
164
- none: false
165
- requirements:
166
- - - ">="
167
- - !ruby/object:Gem::Version
168
- hash: 3
169
- segments:
170
- - 0
171
- version: "0"
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
172
131
  requirements: []
173
-
174
132
  rubyforge_project:
175
- rubygems_version: 1.8.15
133
+ rubygems_version: 2.0.3
176
134
  signing_key:
177
- specification_version: 3
135
+ specification_version: 4
178
136
  summary: JSON-RPC2 server DSL
179
137
  test_files: []
180
-
181
- has_rdoc: