Class: JSONRPC2::Interface

Inherits:
Object
  • Object
show all
Extended by:
TextileEmitter
Defined in:
lib/jsonrpc2/interface.rb

Overview

Base class for JSONRPC2 interface

Class Attribute Summary collapse

Authentication collapse

Rack-related collapse

DSL collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TextileEmitter

about_method, method_to_textile, to_textile, to_textile_group

Constructor Details

#initialize(env) ⇒ Interface

Create new interface object

Parameters:

  • env (Hash)

    Rack environment



119
120
121
122
# File 'lib/jsonrpc2/interface.rb', line 119

def initialize(env)
  @_jsonrpc_env = env
  @_jsonrpc_request = Rack::Request.new(env)
end

Class Attribute Details

.aboutObject (readonly)

Returns the value of attribute about.



365
366
367
# File 'lib/jsonrpc2/interface.rb', line 365

def about
  @about
end

.typesObject (readonly)

Returns the value of attribute types.



365
366
367
# File 'lib/jsonrpc2/interface.rb', line 365

def types
  @types
end

Class Method Details

.___append_param(name, type, options) ⇒ Object

Store parameter in internal hash when building API



240
241
242
243
244
245
246
# File 'lib/jsonrpc2/interface.rb', line 240

def ___append_param name, type, options
  @params ||= []
  unless options.has_key?(:required)
    options[:required] = true
  end
  @params << options.merge({ :name => name, :type => type })
end

.auth_with(*args) ⇒ #check?

Get/set authenticator object for API interface - see Auth and BasicAuth

Parameters:

  • args (#check)

    An object that responds to check(environment, json_call_data)

Returns:

  • (#check, nil)

    Currently set object or nil



47
48
49
50
51
52
53
# File 'lib/jsonrpc2/interface.rb', line 47

def auth_with *args
  if args.empty?
    return @auth_with
  else
    @auth_with = args[0]
  end
end

.call(environment) ⇒ Array<Fixnum, Hash<String,String>, Array<String>>

Rack compatible call handler

Parameters:

  • environment (Hash)

    Rack environment hash

Returns:

  • (Array<Fixnum, Hash<String,String>, Array<String>>)

    Rack-compatible response



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/jsonrpc2/interface.rb', line 63

def call(environment)
  request = Rack::Request.new(environment)
  catch :rack_response do
    best = JSONRPC2::HTTPUtils.which(environment['HTTP_ACCEPT'], %w[text/html application/json-rpc application/json])

    if request.path_info =~ %r'/_assets' or request.path_info == '/favicon.ico'
      best = 'text/html' # hack for assets
    end

    case best
    when 'text/html', 'text/css', 'image/png' # Assume browser
      monitor_time(environment, request.POST['__json__']) { JSONRPC2::HTML.call(self, request) }
    when 'application/json-rpc', 'application/json', nil # Assume correct by default
      environment['rack.input'].rewind
      raw = environment['rack.input'].read
      data = JSON.parse(raw) if raw.to_s.size >= 2
      monitor_time(environment, raw) { self.new(environment).rack_dispatch(data) }
    else
      [406, {'Content-Type' => 'text/html'},
        ["<!DOCTYPE html><html><head><title>Media type mismatch</title></head><body>I am unable to acquiesce to your request</body></html>"]]
    end
  end

rescue Exception => e
  if env['rack.logger'].respond_to?(:error)
    env['rack.logger'].error "#{e.class}: #{e.message} - #{e.backtrace * "\n    "}"
  end
  raise e.class, e.message, e.backtrace
end

.desc(str) ⇒ Object

Set description for next method



282
283
284
# File 'lib/jsonrpc2/interface.rb', line 282

def desc str
  @desc = str
end

.example(desc, code) ⇒ Object

Add an example for next method



287
288
289
290
# File 'lib/jsonrpc2/interface.rb', line 287

def example desc, code
  @examples ||= []
  @examples << { :desc => desc, :code => code }
end

.introduction(str = nil) ⇒ Object

Sets introduction for interface



327
328
329
# File 'lib/jsonrpc2/interface.rb', line 327

def introduction str = nil
  @introduction = str if str
end

.method_added(name) ⇒ Object

Catch methods added to class & store documentation



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/jsonrpc2/interface.rb', line 334

def method_added(name)
  return if self == JSONRPC2::Interface
  @about ||= {}
  method = {}
  method[:params] = @params if @params
  method[:returns] = @result if @result
  method[:desc] = @desc if @desc
  method[:examples] = @examples if @examples
  
  if method.empty?
    if public_methods(false).include?(name)
      unless @nodoc
        #logger.info("#{name} has no API documentation... :(")
      end
    else
      #logger.debug("#{name} isn't public - so no API")
    end
  else
    method[:name] = name
    method[:section] = @current_section
    method[:index] = @about.size
    @about[name.to_s] = method
  end

  @result = nil
  @params = nil
  @desc = nil
  @examples = nil
  @nodoc = false
end

.nodocObject

Exclude next method from documentation



317
318
319
# File 'lib/jsonrpc2/interface.rb', line 317

def nodoc
  @nodoc = true
end

.optional(name, type, desc = nil, options = nil) ⇒ Object

Define an optional parameter for next method



266
267
268
269
270
271
272
273
274
# File 'lib/jsonrpc2/interface.rb', line 266

def optional name, type, desc = nil, options = nil
  if options.nil? && desc.is_a?(Hash)
    options, desc = desc, nil
  end
  options ||= {}
  options[:desc] = desc if desc.is_a?(String)

  ___append_param(name, type, options.merge(:required => false))
end

.param(name, type, desc = nil, options = nil) ⇒ Object

Define a named parameter of type #type for next method

Parameters:

  • name (String)

    parameter name

  • type (String)

    description of type see Types



255
256
257
258
259
260
261
262
263
# File 'lib/jsonrpc2/interface.rb', line 255

def param name, type, desc = nil, options = nil
  if options.nil? && desc.is_a?(Hash)
    options, desc = desc, nil
  end
  options ||= {}
  options[:desc] = desc if desc.is_a?(String)
  
  ___append_param name, type, options
end

.result(type, desc = nil) ⇒ Object

Define type of return value for next method



277
278
279
# File 'lib/jsonrpc2/interface.rb', line 277

def result type, desc = nil
  @result = { :type => type, :desc => desc }
end

.section(name, summary = nil) ⇒ Object

Group methods



305
306
307
308
309
310
311
312
313
314
# File 'lib/jsonrpc2/interface.rb', line 305

def section name, summary=nil
  @sections ||= []
  @sections << {:name => name, :summary => summary}

  @current_section = name
  if block_given?
    yield
    @current_section = nil
  end
end

.title(str = nil) ⇒ Object

Set interface title



322
323
324
# File 'lib/jsonrpc2/interface.rb', line 322

def title str = nil
  @title = str if str
end

.type(name, *fields) ⇒ Object

Define a custom type



293
294
295
296
297
298
299
300
301
302
# File 'lib/jsonrpc2/interface.rb', line 293

def type name, *fields
  @types ||= {}
  type = JsonObjectType.new(name, fields)

  if block_given?
    yield(type)
  end

  @types[name] = type
end

Instance Method Details

#dispatch(rpc_data) ⇒ Hash, Array

Dispatch call to api method(s)

Parameters:

  • rpc_data (Hash, Array)

    Array of calls or Hash containing one call

Returns:

  • (Hash, Array)

    Depends on input, but either a hash result or an array of results corresponding to calls.



135
136
137
138
139
140
141
142
# File 'lib/jsonrpc2/interface.rb', line 135

def dispatch(rpc_data)
  case rpc_data
  when Array
    rpc_data.map { |rpc| dispatch_single(rpc) }.to_json
  else
    dispatch_single(rpc_data).to_json
  end
end

#rack_dispatch(rpcData) ⇒ Object

Internal



124
125
126
127
128
129
# File 'lib/jsonrpc2/interface.rb', line 124

def rack_dispatch(rpcData)
  catch(:rack_response) do
    json = dispatch(rpcData)
    [200, {'Content-Type' => 'application/json-rpc'}, [json]]
  end
end