jsonrpc2 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,22 @@
2
2
 
3
3
  A Rack compatible, documenting JSON-RPC 2 DSL/server implementation for ruby.
4
4
 
5
+ ## Changes
6
+
7
+ * 0.0.8 - 3-Sep-2012
8
+ Add #request to access Rack::Request object
9
+ Make URLs in HTML interface clickable
10
+
11
+ * 0.0.7 - 27-Aug-2012
12
+ Add bundled Bootstrap assets for HTML test interface
13
+
14
+ * 0.0.6 - 24-Aug-2012
15
+ Add Date/Time/DateTime as special string types with regex checks for validation
16
+
17
+ * 0.0.5 - 19-Jul-2012
18
+ Add commandline client jsonrpc2
19
+ Add #auth to access currently authenticated username
20
+
5
21
  ## Features
6
22
 
7
23
  * Inline documentation
@@ -167,9 +167,12 @@ EOS
167
167
  end
168
168
  # Format JSON result
169
169
  def format_result(result)
170
- CGI.escapeHTML(JSON.pretty_unparse(JSON.parse(result)))
171
- rescue Exception
172
- result
170
+ CGI.escapeHTML(JSON.pretty_unparse(JSON.parse(result))).gsub(%r<("|&quot;)https?://[^"]+?("|&quot;)>) do |str|
171
+ url = CGI.unescapeHTML(str)[1...-1]
172
+ %Q["<a href="#{CGI.escapeHTML(url)}">#{CGI.escapeHTML(url)}</a>"]
173
+ end
174
+ rescue Exception => e
175
+ CGI.escapeHTML(result.to_s)
173
176
  end
174
177
  end
175
178
  end
@@ -17,7 +17,7 @@ module JSONRPC2
17
17
 
18
18
  # Base class for JSONRPC2 interface
19
19
  class Interface
20
- class << self
20
+ class << self
21
21
 
22
22
  # @!group Authentication
23
23
 
@@ -25,13 +25,13 @@ class Interface
25
25
  #
26
26
  # @param [#check] args An object that responds to check(environment, json_call_data)
27
27
  # @return [#check, nil] Currently set object or nil
28
- def auth_with *args
29
- if args.empty?
30
- return @auth_with
31
- else
32
- @auth_with = args[0]
33
- end
34
- end
28
+ def auth_with *args
29
+ if args.empty?
30
+ return @auth_with
31
+ else
32
+ @auth_with = args[0]
33
+ end
34
+ end
35
35
 
36
36
  # @!endgroup
37
37
 
@@ -66,14 +66,15 @@ class Interface
66
66
 
67
67
  # @!endgroup
68
68
 
69
- end
69
+ end
70
70
 
71
71
  # Create new interface object
72
72
  #
73
73
  # @param [Hash] env Rack environment
74
- def initialize(env)
75
- @env = env
76
- end
74
+ def initialize(env)
75
+ @_jsonrpc_env = env
76
+ @_jsonrpc_request = Rack::Request.new(env)
77
+ end
77
78
  # Internal
78
79
  def rack_dispatch(rpcData)
79
80
  catch(:rack_response) do
@@ -87,54 +88,58 @@ class Interface
87
88
  # @param [Hash,Array] rpc_data Array of calls or Hash containing one call
88
89
  # @return [Hash,Array] Depends on input, but either a hash result or an array of results corresponding to calls.
89
90
  def dispatch(rpc_data)
90
- case rpc_data
91
+ case rpc_data
91
92
  when Array
92
- rpc_data.map { |rpc| dispatch_single(rpc) }.to_json
93
- else
94
- dispatch_single(rpc_data).to_json
95
- end
96
- end
93
+ rpc_data.map { |rpc| dispatch_single(rpc) }.to_json
94
+ else
95
+ dispatch_single(rpc_data).to_json
96
+ end
97
+ end
97
98
 
98
- protected
99
+ protected
99
100
  # JSON result helper
100
- def response_ok(id, result)
101
- { 'jsonrpc' => '2.0', 'result' => result, 'id' => id }
102
- end
101
+ def response_ok(id, result)
102
+ { 'jsonrpc' => '2.0', 'result' => result, 'id' => id }
103
+ end
103
104
  # JSON error helper
104
- def response_error(code, message, data)
105
- { 'jsonrpc' => '2.0', 'error' => { 'code' => code, 'message' => message, 'data' => data }, 'id' => (@jsonrpc_call && @jsonrpc_call['id'] || nil) }
106
- end
105
+ def response_error(code, message, data)
106
+ { 'jsonrpc' => '2.0', 'error' => { 'code' => code, 'message' => message, 'data' => data }, 'id' => (@_jsonrpc_call && @_jsonrpc_call['id'] || nil) }
107
+ end
107
108
  # Params helper
108
109
  def params
109
- @jsonrpc_call['params']
110
+ @_jsonrpc_call['params']
110
111
  end
111
112
  # Auth info
112
113
  def auth
113
- @jsonrpc_auth
114
+ @_jsonrpc_auth
115
+ end
116
+ # Rack::Request
117
+ def request
118
+ @_jsonrpc_request
114
119
  end
115
120
  # Check call validity and authentication & make a single method call
116
121
  #
117
122
  # @param [Hash] rpc JSON-RPC-2 call
118
- def dispatch_single(rpc)
119
- unless rpc.has_key?('id') && rpc.has_key?('method') && rpc['jsonrpc'].eql?('2.0')
120
- return response_error(-32600, 'Invalid request', nil)
121
- end
122
- @jsonrpc_call = rpc
123
-
124
- begin
125
- if self.class.auth_with && ! @jsonrpc_auth
126
- (@jsonrpc_auth = self.class.auth_with.client_check(@env, rpc)) or raise AuthFail, "Invalid credentials"
123
+ def dispatch_single(rpc)
124
+ unless rpc.has_key?('id') && rpc.has_key?('method') && rpc['jsonrpc'].eql?('2.0')
125
+ return response_error(-32600, 'Invalid request', nil)
126
+ end
127
+ @_jsonrpc_call = rpc
128
+
129
+ begin
130
+ if self.class.auth_with && ! @_jsonrpc_auth
131
+ (@_jsonrpc_auth = self.class.auth_with.client_check(@_jsonrpc_env, rpc)) or raise AuthFail, "Invalid credentials"
127
132
  end
128
133
 
129
- call(rpc['method'], rpc['id'], rpc['params'])
130
- rescue AuthFail => e
131
- response_error(-32000, "AuthFail: #{e.class}: #{e.message}", {}) # XXX: Change me
132
- rescue APIFail => e
133
- response_error(-32000, "APIFail: #{e.class}: #{e.message}", {}) # XXX: Change me
134
- rescue Exception => e
135
- response_error(-32000, "#{e.class}: #{e.message}", e.backtrace) # XXX: Change me
136
- end
137
- end
134
+ call(rpc['method'], rpc['id'], rpc['params'])
135
+ rescue AuthFail => e
136
+ response_error(-32000, "AuthFail: #{e.class}: #{e.message}", {}) # XXX: Change me
137
+ rescue APIFail => e
138
+ response_error(-32000, "APIFail: #{e.class}: #{e.message}", {}) # XXX: Change me
139
+ rescue Exception => e
140
+ response_error(-32000, "#{e.class}: #{e.message}", e.backtrace) # XXX: Change me
141
+ end
142
+ end
138
143
  # List API methods
139
144
  #
140
145
  # @return [Array] List of api method names
@@ -148,41 +153,41 @@ class Interface
148
153
  # @param [Integer] id Method call ID - for response
149
154
  # @param [Hash] params Method parameters
150
155
  # @return [Hash] JSON response
151
- def call(method, id, params)
152
- if api_methods.include?(method)
153
- begin
154
- Types.valid_params?(self.class, method, params)
155
- rescue Exception => e
156
- return response_error(-32602, "Invalid params - #{e.message}", {})
157
- end
156
+ def call(method, id, params)
157
+ if api_methods.include?(method)
158
+ begin
159
+ Types.valid_params?(self.class, method, params)
160
+ rescue Exception => e
161
+ return response_error(-32602, "Invalid params - #{e.message}", {})
162
+ end
158
163
 
159
164
  if self.method(method).arity.zero?
160
- result = send(method)
165
+ result = send(method)
161
166
  else
162
- result = send(method, params)
167
+ result = send(method, params)
163
168
  end
164
169
 
165
- begin
166
- Types.valid_result?(self.class, method, result)
167
- rescue Exception => e
168
- return response_error(-32602, "Invalid result - #{e.message}", {})
169
- end
170
-
171
- response_ok(id, result)
172
- else
173
- response_error(-32601, "Unknown method `#{method.inspect}'", {})
174
- end
175
- end
176
-
177
- class << self
170
+ begin
171
+ Types.valid_result?(self.class, method, result)
172
+ rescue Exception => e
173
+ return response_error(-32602, "Invalid result - #{e.message}", {})
174
+ end
175
+
176
+ response_ok(id, result)
177
+ else
178
+ response_error(-32601, "Unknown method `#{method.inspect}'", {})
179
+ end
180
+ end
181
+
182
+ class << self
178
183
  # Store parameter in internal hash when building API
179
- def ___append_param name, type, options
180
- @params ||= []
181
- unless options.has_key?(:required)
182
- options[:required] = true
183
- end
184
- @params << options.merge({ :name => name, :type => type })
185
- end
184
+ def ___append_param name, type, options
185
+ @params ||= []
186
+ unless options.has_key?(:required)
187
+ options[:required] = true
188
+ end
189
+ @params << options.merge({ :name => name, :type => type })
190
+ end
186
191
  private :___append_param
187
192
 
188
193
  # @!group DSL
@@ -191,119 +196,119 @@ class Interface
191
196
  #
192
197
  # @param [String] name parameter name
193
198
  # @param [String] type description of type see {Types}
194
- def param name, type, desc = nil, options = nil
195
- if options.nil? && desc.is_a?(Hash)
196
- options, desc = desc, nil
197
- end
198
- options ||= {}
199
- options[:desc] = desc if desc.is_a?(String)
200
-
201
- ___append_param name, type, options
202
- end
199
+ def param name, type, desc = nil, options = nil
200
+ if options.nil? && desc.is_a?(Hash)
201
+ options, desc = desc, nil
202
+ end
203
+ options ||= {}
204
+ options[:desc] = desc if desc.is_a?(String)
205
+
206
+ ___append_param name, type, options
207
+ end
203
208
 
204
209
  # Define an optional parameter for next method
205
- def optional name, type, desc = nil, options = nil
206
- if options.nil? && desc.is_a?(Hash)
207
- options, desc = desc, nil
208
- end
209
- options ||= {}
210
- options[:desc] = desc if desc.is_a?(String)
210
+ def optional name, type, desc = nil, options = nil
211
+ if options.nil? && desc.is_a?(Hash)
212
+ options, desc = desc, nil
213
+ end
214
+ options ||= {}
215
+ options[:desc] = desc if desc.is_a?(String)
211
216
 
212
- ___append_param(name, type, options.merge(:required => false))
213
- end
217
+ ___append_param(name, type, options.merge(:required => false))
218
+ end
214
219
 
215
220
  # Define type of return value for next method
216
- def result type, desc = nil
217
- @result = { :type => type, :desc => desc }
218
- end
221
+ def result type, desc = nil
222
+ @result = { :type => type, :desc => desc }
223
+ end
219
224
 
220
225
  # Set description for next method
221
- def desc str
222
- @desc = str
223
- end
226
+ def desc str
227
+ @desc = str
228
+ end
224
229
 
225
230
  # Add an example for next method
226
- def example desc, code
227
- @examples ||= []
228
- @examples << { :desc => desc, :code => code }
229
- end
231
+ def example desc, code
232
+ @examples ||= []
233
+ @examples << { :desc => desc, :code => code }
234
+ end
230
235
 
231
236
  # Define a custom type
232
- def type name, *fields
233
- @types ||= {}
234
- type = JsonObjectType.new(name, fields)
237
+ def type name, *fields
238
+ @types ||= {}
239
+ type = JsonObjectType.new(name, fields)
235
240
 
236
- if block_given?
237
- yield(type)
238
- end
241
+ if block_given?
242
+ yield(type)
243
+ end
239
244
 
240
- @types[name] = type
241
- end
245
+ @types[name] = type
246
+ end
242
247
 
243
248
  # Group methods
244
- def section name, summary=nil
245
- @sections ||= []
246
- @sections << {:name => name, :summary => summary}
247
-
248
- @current_section = name
249
- if block_given?
250
- yield
251
- @current_section = nil
252
- end
253
- end
249
+ def section name, summary=nil
250
+ @sections ||= []
251
+ @sections << {:name => name, :summary => summary}
252
+
253
+ @current_section = name
254
+ if block_given?
255
+ yield
256
+ @current_section = nil
257
+ end
258
+ end
254
259
 
255
260
  # Exclude next method from documentation
256
- def nodoc
257
- @nodoc = true
258
- end
261
+ def nodoc
262
+ @nodoc = true
263
+ end
259
264
 
260
265
  # Set interface title
261
- def title str = nil
262
- @title = str if str
263
- end
266
+ def title str = nil
267
+ @title = str if str
268
+ end
264
269
 
265
270
  # Sets introduction for interface
266
- def introduction str = nil
267
- @introduction = str if str
268
- end
271
+ def introduction str = nil
272
+ @introduction = str if str
273
+ end
269
274
 
270
275
  # @!endgroup
271
276
 
272
277
  # Catch methods added to class & store documentation
273
- def method_added(name)
274
- return if self == JSONRPC2::Interface
275
- @about ||= {}
276
- method = {}
277
- method[:params] = @params if @params
278
- method[:returns] = @result if @result
279
- method[:desc] = @desc if @desc
280
- method[:examples] = @examples if @examples
281
-
282
- if method.empty?
283
- if public_methods(false).include?(name)
284
- unless @nodoc
285
- #logger.info("#{name} has no API documentation... :(")
286
- end
287
- else
288
- #logger.debug("#{name} isn't public - so no API")
289
- end
290
- else
291
- method[:name] = name
292
- method[:section] = @current_section
293
- method[:index] = @about.size
294
- @about[name.to_s] = method
295
- end
296
-
297
- @result = nil
298
- @params = nil
299
- @desc = nil
300
- @examples = nil
301
- @nodoc = false
302
- end
278
+ def method_added(name)
279
+ return if self == JSONRPC2::Interface
280
+ @about ||= {}
281
+ method = {}
282
+ method[:params] = @params if @params
283
+ method[:returns] = @result if @result
284
+ method[:desc] = @desc if @desc
285
+ method[:examples] = @examples if @examples
286
+
287
+ if method.empty?
288
+ if public_methods(false).include?(name)
289
+ unless @nodoc
290
+ #logger.info("#{name} has no API documentation... :(")
291
+ end
292
+ else
293
+ #logger.debug("#{name} isn't public - so no API")
294
+ end
295
+ else
296
+ method[:name] = name
297
+ method[:section] = @current_section
298
+ method[:index] = @about.size
299
+ @about[name.to_s] = method
300
+ end
301
+
302
+ @result = nil
303
+ @params = nil
304
+ @desc = nil
305
+ @examples = nil
306
+ @nodoc = false
307
+ end
303
308
  private :method_added
304
- attr_reader :about, :types
309
+ attr_reader :about, :types
305
310
 
306
- end
311
+ end
307
312
 
308
313
  extend JSONRPC2::TextileEmitter
309
314
  end
@@ -1,5 +1,5 @@
1
1
  # JSONRPC2 namespace module
2
2
  module JSONRPC2
3
3
  # Version
4
- VERSION = "0.0.7"
4
+ VERSION = "0.0.8"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonrpc2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
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: 2012-08-27 00:00:00.000000000 Z
12
+ date: 2012-09-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httpclient