class ActiveRpc::RackServer

Attributes

request[R]

Public Class Methods

call(env) click to toggle source
# File lib/active_rpc/rack_server.rb, line 3
def self.call(env)
  new(Rack::Request.new(env)).call
end
new(request) click to toggle source
# File lib/active_rpc/rack_server.rb, line 9
def initialize(request)
  @request = request
end

Public Instance Methods

call() click to toggle source
# File lib/active_rpc/rack_server.rb, line 13
def call
  res = nil
  begin
    res = case body
          when Array then body.map(&method(:process_item)).map(&:to_hash)
          when Hash then process_item(body).to_hash
          end
  rescue JSON::ParserError => ex
    res = ActiveRpc::Response.new do |r|
      r.error = Errors::ParseError.new(message: ex.to_s)
    end.to_hash
  end

  [
    200,
    {'Content-Type' => 'application/json'},
    [JSON.generate(res)]
  ]
end

Private Instance Methods

body() click to toggle source
# File lib/active_rpc/rack_server.rb, line 65
        def body
  @body ||= JSON.load(request.body.read)
end
process_item(item) click to toggle source
# File lib/active_rpc/rack_server.rb, line 33
        def process_item(item)
  req = ActiveRpc::Request.new(item.slice('id', 'method', 'params'))
  res = ActiveRpc::Response.from_request(req)
  ex = nil

  begin
    raise TypeError, 'invalid JSON-RPC request' unless req.valid?

    executor = ActiveRpc.get_executor(req.method)
    raise NoMethodError, "undefined operation `#{req.method}'" unless executor

    ex = executor.new(req.params)
    raise ArgumentError, 'invalid payload' unless ex.valid?
    res.result = ex.call
  rescue TypeError => e
    res.error = Errors::ClientError.new(message: e.to_s)
    res.error.data = req.errors
  rescue NoMethodError => e
    res.error = Errors::NoMethodError.new(message: e.to_s)
  rescue ArgumentError => e
    res.error = Errors::ArgumentError.new(message: e.to_s)
    res.error.data = ex.errors
  rescue OperationFailure => e
    res.error = e.rpc_error
  # todo: handle rpc-level errors
  rescue => e
    res.error = Errors::InternalError.new(message: e.to_s)
  end

  res
end