Project

hobby-rpc

0.0
The project is in a healthy, maintained state
A simple RPC system for callable Ruby constants. It allows to expose them over HTTP safely, only to authorized users.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
 Project Readme

Introduction

Hobby-RPC is a simple RPC system for callable Ruby constants. It allows to expose them over HTTP safely, only to authorized users.

It is available on RubyGems as hobby-rpc.

Usage

Defining user roles

First, we need to define who the users are and what they can do. Otherwise, all the requests will return 403 Forbidden.

We can do this by creating at least one user role. A user role is a class that includes Hobby::RPC::User and implements .find_by_token and #can? methods. For example:

class Client
  include Hobby::RPC::User

  # Accepts a `token`(String).
  #
  # Here we can look up at the place where we store active sessions.
  # It could be a Redis server mapping session tokens to users.
  #
  # Returns a user or nil(if a session for such token does not exist).
  def self.find_by_token token
    new if 'the token' == token
  end

  # Accepts a `function`(String).
  #
  # This determines what a user can do. A user will be allowed to call
  # `function` only when this method returns truthy value.
  #
  # One way to implement it is with Redis Sets:
  # https://redis.io/commands/sismember
  def can? function
    ['SomeFunction', 'SomeNamespace::SomeFunction'].include? function
  end

Client is the only role at the moment, but we can define as many as we would like. The role names would be specific to the business logic of your application.

Defining functions

An RPC function is a Ruby constant whose object implements .call method that can accept user and input parameters. It can accept them either as a Hash or as keyword arguments. For example:

module SomeFunction
  def self.call hash
    hash[:user]
    hash[:input]
    'return any value serializable to JSON'
  end
end

module SomeNamespace
  module SomeFunction
    def self.call user:, input:
      'return any value serializable to JSON'
    end
  end
end

A user would be an instance of a user role defined earlier.

Running a server

To start a server, we can use rackup. For that, we can put the following into config.ru:

require 'hobby/rpc'
run Hobby::RPC.new

Or we can use Puma directly as follows:

require 'hobby/rpc'
require 'puma'

server = Puma::Server.new Hobby::RPC.new
server.add_tcp_listener '127.0.0.1', port
server.run
sleep

By default, it will return permissive CORS headers for requests from any origin. You can restrict the origins from which requests will be accepted as follows:

Hobby::RPC.new cors_origins: ['https://some.domain', 'https://another.domain']

Calling functions

To call RPC functions from browsers, you can use this client.

Development

To work on hobby-rpc itself, you can build the project and run the tests:

bundle exec rake