Skip to content

Commit

Permalink
Introduce custom application error with optional data object (#216)
Browse files Browse the repository at this point in the history
This addresses two items:
- Use ApplicationError instead of InvalidRequest for custom
application errors. Avoiding confusing regarding the usage of
InvalidRequest (although the actual error code used could/would
be different).
- Allow for defining an optional data object that gets returned
in the error response, as per json-rpc specification.
  • Loading branch information
kdeme committed Mar 4, 2024
1 parent 8682bb6 commit a20ba20
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
17 changes: 14 additions & 3 deletions json_rpc/errors.nim
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
# json-rpc
# Copyright (c) 2019-2023 Status Research & Development GmbH
# Copyright (c) 2019-2024 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.

{.push raises: [].}

import results, json_serialization

type
JsonRpcError* = object of CatchableError
## Base type of all nim-json-rpc errors
Expand All @@ -28,8 +32,7 @@ type
RpcAddressUnresolvableError* = object of JsonRpcError

InvalidRequest* = object of JsonRpcError
## This could be raised by request handlers when the server
## needs to respond with a custom error code.
## raised when the server recieves an invalid JSON request object
code*: int

RequestDecodeError* = object of JsonRpcError
Expand All @@ -38,3 +41,11 @@ type
ParamsEncodeError* = object of JsonRpcError
## raised when fail to encode RequestParamsTx

ApplicationError* = object of JsonRpcError
## Error to be raised by the application request handlers when the server
## needs to respond with a custom application error. The error code should
## be outside the range of -32768 to -32000. A custom JSON data object may
## be provided.
code*: int
message*: string
data*: results.Opt[JsonString]
9 changes: 9 additions & 0 deletions json_rpc/router.nim
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ func serverError(msg: string, data: JsonString): ResponseError =
func somethingError(code: int, msg: string): ResponseError =
ResponseError(code: code, message: msg)

func applicationError(code: int, msg: string, data: Opt[JsonString]): ResponseError =
ResponseError(code: code, message: msg, data: data)

proc validateRequest(router: RpcRouter, req: RequestRx):
Result[RpcProc, ResponseError] =
if req.jsonrpc.isNone:
Expand Down Expand Up @@ -131,9 +134,15 @@ proc route*(router: RpcRouter, req: RequestRx):
try:
let res = await rpcProc(req.params)
return wrapReply(res, req.id)
except ApplicationError as err:
return wrapError(applicationError(err.code, err.msg, err.data), req.id)
except InvalidRequest as err:
# TODO: deprecate / remove this usage and use InvalidRequest only for
# internal errors.
return wrapError(err.code, err.msg, req.id)
except CatchableError as err:
# Note: Errors that are not specifically raised as `ApplicationError`s will
# be returned as custom server errors.
let methodName = req.meth.get # this Opt already validated
debug "Error occurred within RPC",
methodName = methodName, err = err.msg
Expand Down

0 comments on commit a20ba20

Please sign in to comment.