Receiving a JSON-RPC request
Before receiving any request, you should have already established a connection.
When a request is received, the router matches it to a server method by name. If no matching server method can be found the request is dropped, and an error is returned to the client if the client requested a response.
When an RPC-invoked server method throws an exception, the server will handle the exception and (when applicable) send an error response to the client with a description of the failure.
JSON-RPC is an inherently asynchronous protocol. Multiple concurrent requests are allowed. Methods are invoked as the requests are processed, even while prior requests are still running.
Method format flavor
A format flavor to convert the request parameters and the response result to/from JSON must be created to use in the RPC methods:
createJsonFlavor RpcConv,
automaticObjectSerialization = false,
automaticPrimitivesSerialization = true,
requireAllFields = false,
omitOptionalFields = true, # Skip optional fields==none in Writer
allowUnknownFields = true,
skipNullFields = true # Skip optional fields==null in Reader
Registering methods
The rpc macro accepts a list of proc definitions which are registered as RPC methods. The procedures can be synchronous or async, both run within the async event loop. Procedure overload is not supported.
Synchronous RPC methods are implemented as regular procs:
srv.rpc(RpcConv):
proc hello(input: string): string =
"Hello " & input
Async RPC methods are supported with {.async.}:
proc howdy(input: string): string {.async: (raises: []).} =
"Howdy " & input
When named parameters are used, serializedFieldName can be used to customize the field name:
proc bye(input {.serializedFieldName: "user-name".}: string): string =
"Bye " & input
Wrapping the method name in backticks allows any character:
proc `👑`(input: string): string =
"👑 " & input
When the procedure return type is not specified, JsonNode is implicitly used. To avoid returning a result, void can be used instead:
proc empty(): void =
echo "nothing"
Compiling with -d:nimDumpRpcs will show the output code for the RPC call. To see the output of the async generation, add -d:nimDumpAsync.
Parameter name and placement
RPC servers should consider their methods as public API that requires stability. The following changes to a method's signature can be considered breaking:
- Renaming parameters will break clients that pass parameter by name.
- Reordering parameters will break clients that pass parameter by position.
- Removing parameters.
- Removing a method.
- Adding non-optional parameters.
The following changes to a method's signature can be considered non-breaking:
- Adding optional parameters as last parameter.
- Changing the parameter type, if it remains compatible with the wire format representation for the value.
Throwing exceptions
RPC methods can return errors to the client by throwing an exception.