JSONRPC2Plug (jsonrpc2_plug v0.1.0)
JSON-RPC 2.0 plug
JSONRPC2Plug
is an Elixir library for a JSON-RPC 2.0 server. Can be used as the plug middleware or as a standalone transport-agnostic server handler.
installation
Installation
The package can be installed by adding jsonrpc2_plug
to your list of dependencies in mix.exs
:
def deps do
[
{:jsonrpc2_plug, "~> 0.1.0"}
]
end
usage
Usage
defining-services
Defining Services
Services should use JSONRPC2Plug.Service
, which allows describing methods of service. Each method is a module which use JSONRPC2Plug.Method
.
Examples:
defmodule CalculatorService do
use JSONRPC2Plug.Service
method "add", AddMethod
method "subtract", SubtractMethod
method "multiply", MultiplyMethod
method "divide", DivideMethod
end
defmodule AddMethod do
use JSONRPC2Plug.Method
end
# and so on...
defining-methods
Defining Methods
There are two possible ways to execute a request: call
and cast
. The first assumes the response which the service will return, the second does not. The module should implement at least one handle_call
or handle_cast
callback function to handle requests.
defmodule AddMethod do
use JSONRPC2Plug.Method
# It handles requests like this:
# {"id": "123", "method": "add", "params": {"x": 10, "y": 20}, "jsonrpc": "2.0"}
def handle_call(%{"x" = > x, "y" => y}, _conn) do
{:ok, x + y}
end
end
The first argument is the "params"
data comes from request JSON. According to JSONRPC2 spec, it must be either object or an array of arguments.
The second argument is the Plug.Conn
struct. Sometimes it could be useful to access the Plug
connection.
The module implements behaviour JSONRPC2Plug.Method
which consists of five callbacks: handle_call
, handle_cast
, validate
, handle_error
and, handle_exception
.
handle_call
and handle_cast
TODO: Add description
validate
This function is for the validation of the input dataset.
import JSONRPC2Plug.Validator, only: [type: 1, required: 0]
def validate(params) do
params
|> Validator.validate("x", [type(:integer), required()])
|> Validator.validate("y", [type(:integer), required()])
|> Validator.unwrap()
end
The library has its own validator. It has 8 built-in validations: type
, required
, not_empty
, exclude
, include
, len
, number
and format
. However, you can write custom validations and extend existing ones.
Moreover, you can use any preferred validator (eg. valdi
), but you should respect the following requirements: the validate
function should return either {:ok, params}
or {:invalid, errors}
. Where errors
could be any type that can be safely encoded to JSON and params
is params to pass into handle_call
or handle_cast
functions.
handle_error
and handle_exception
TODO: Add description
add-as-a-plug-to-the-router
Add as a plug to the router
TODO: Add description
using-as-standalone-module
Using as standalone module
TODO: Add description
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/jsonrpc2_plug.
Link to this section Summary
Functions
HTTP entry point to JSONRPC 2.0 services. It's usual plug and accepts service handler module as a param.
Send an error encoded according to JSONRPC 2.0 spec. It can be useful for global error handler in the router.
Link to this section Functions
call(conn, handler)
Specs
call(Plug.Conn.t(), Plug.opts()) :: Plug.Conn.t()
HTTP entry point to JSONRPC 2.0 services. It's usual plug and accepts service handler module as a param.
Example:
use Plug.Router
forward "/jsonrpc", to: JSONRPC2Plug, init_opts: CalculatorService
send_error(conn, kind, ex)
Specs
send_error(Plug.Conn.t(), atom(), struct()) :: Plug.Conn.t()
Send an error encoded according to JSONRPC 2.0 spec. It can be useful for global error handler in the router.
Example:
forward "/jsonrpc", to: JSONRPC2Plug, init_opts: CalculatorService
@impl Plug.ErrorHandler
def handle_errors(conn, %{kind: kind, reason: reason, stack: stacktrace}) do
Logger.error(Exception.format(kind, reason, stacktrace))
case conn do
%{request_path: "/jsonrpc"} ->
JSONRPC2Plug.send_error(conn, kind, reason)
_ ->
send_resp(conn, 500, "Someting went wrong")
end
end