class MetaRPC::Interpreter

Used to interpret RPC requests and execute them securely

Attributes

input[R]

Public Class Methods

new(raw_request) click to toggle source
# File lib/metarpc/interpreter.rb, line 6
def initialize(raw_request)
  raw_input = JSON.parse(raw_request)

  @input = if raw_input.is_a?(Array)
             raw_input.map(&method(:validate_json_rpc_call))
           else
             validate_json_rpc_call(raw_input)
           end
rescue JSON::ParserError
  raise_error(:parse_error)
end

Public Instance Methods

execute(executor) click to toggle source
# File lib/metarpc/interpreter.rb, line 18
def execute(executor)
  return input.map { |inp| execute_method(executor, inp) } if input.is_a?(Array)

  execute_method(executor, input)
end
execute_method(executor, inp) click to toggle source
# File lib/metarpc/interpreter.rb, line 24
def execute_method(executor, inp)
  raise_error(:method_not_found) unless executor.class.json_rpc_methods.key?(inp[:method])

  result = if inp[:params].is_a?(Array)
             executor.public_send(inp[:method], *inp[:params])
           elsif inp[:params].is_a?(Hash)
             executor.public_send(inp[:method], inp[:params])
           elsif inp[:params].nil?
             executor.public_send(inp[:method])
           else
             raise_error(:internal_error)
           end

  {
    jsonrpc: '2.0',
    result: result,
    id: inp[:id]
  }
rescue RPCError => err
  {
    jsonrpc: '2.0',
    error: err.to_h,
    id: inp[:id]
  }
end
raise_error(code) click to toggle source
# File lib/metarpc/interpreter.rb, line 92
def raise_error(code)
  raise RPCError.new(code), "Error on interpreter : #{code}"
end
valid_id(id) click to toggle source
# File lib/metarpc/interpreter.rb, line 76
def valid_id(id)
  return true if id.nil?

  id.is_a?(String) || id.nil? || id.is_a?(Integer) || id.is_a?(Float)
end
valid_method_name(method) click to toggle source
# File lib/metarpc/interpreter.rb, line 88
def valid_method_name(method)
  method.is_a?(String) && !method.start_with?('rpc.')
end
valid_params(params) click to toggle source
# File lib/metarpc/interpreter.rb, line 82
def valid_params(params)
  return true if params.nil?

  params.is_a?(Array) || params.is_a?(Hash)
end
validate_json_rpc_call(item) click to toggle source
# File lib/metarpc/interpreter.rb, line 50
def validate_json_rpc_call(item)
  # Containing the required key
  valid = item.key?('jsonrpc') && item.key?('method')

  # Does not contain unknown keys
  valid &&= (item.keys - %w[jsonrpc method params id]).empty?

  # Defining the correct JSONRPC version
  valid &&= item['jsonrpc'] == '2.0'

  # Defining a correct ID
  valid &&= valid_id(item['id'])

  # Defining a correct params object
  valid &&= valid_params(item['params'])

  # Defining a correct method name
  valid &&= valid_method_name(item['method'])

  raise_error(:invalid_request) unless valid

  item.deep_symbolize_keys.tap do |h|
    h[:method] = h[:method].to_sym
  end
end