1 // Written in D programming language 2 /** 3 * JSON-RPC 2.0 Protocol<br> 4 * 5 * $(B This module contain JSON-RPC 2.0 errors) 6 * 7 * See_Also: 8 * $(LINK http://www.jsonrpc.org/specification) 9 * 10 * Copyright: © 2014 DSoftOut 11 * License: Subject to the terms of the MIT license, as written in the included LICENSE file. 12 * Authors: Zaramzan <shamyan.roman@gmail.com> 13 */ 14 module json_rpc.error; 15 16 import std.exception; 17 18 import vibe.data.bson; 19 20 import util; 21 22 /** 23 * Contains JSON-RPC 2.0 error codes 24 * 25 * Authors: Zaramzan <shamyan.roman@gmail.com> 26 */ 27 enum RPC_ERROR_CODE:int 28 { 29 NONE, 30 31 PARSE_ERROR = -32700, 32 33 INVALID_REQUEST = -32600, 34 35 METHOD_NOT_FOUND = -32601, 36 37 INVALID_PARAMS = -32602, 38 39 INTERNAL_ERROR = -32603, 40 41 SERVER_ERROR = -32000, 42 43 SERVER_ERROR_EXT = -32099 44 } 45 46 /// Supported JSON-RPC protocol version 47 enum RPC_VERSION = "2.0"; 48 49 /** 50 * Struct describes JSON-RPC 2.0 error object which used in RpcRequest 51 * 52 * Example 53 * ------ 54 * auto err1 = RpcError(bson); 55 * auto err2 = RpcError(RPC_ERROR_CODE.INVALID_PARAMS, "Invalid params"); 56 * auto err3 = RpcError(RPC_ERROR_CODE.INVALID_PARAMS, "mycustommessage"); 57 * auto err4 = RpcError(RPC_ERROR_CODE.INVALID_PARAMS, "Invalid params", erroData); 58 * auto err5 = RpcError(new RpcInvalidParams()); 59 * 60 * //toJson 61 * err2.toJson(); 62 * ------ 63 * 64 * Authors: Zaramzan <shamyan.roman@gmail.com> 65 */ 66 struct RpcError 67 { 68 @required 69 string message; 70 71 @required 72 int code; 73 74 @possible 75 Json data = Json(null); 76 77 this(in Bson bson) 78 { 79 this = tryEx!(RpcInternalError, deserializeFromJson!RpcError)(bson.toJson); 80 } 81 82 this(RPC_ERROR_CODE code, string message) 83 { 84 this.code = code; 85 this.message = message; 86 } 87 88 this (RPC_ERROR_CODE code, string message, Json errorData) 89 { 90 this.data = errorData; 91 92 this(code, message); 93 } 94 95 this(RpcException ex) 96 { 97 this(ex.code, ex.msg); 98 } 99 100 Json toJson() 101 { 102 Json ret = Json.emptyObject; 103 104 ret.code = code; 105 106 ret.message = message; 107 108 if (data.type != Json.Type.null_) 109 { 110 ret.data = data; 111 } 112 113 return ret; 114 } 115 } 116 117 118 /// Super class for all JSON-RPC exceptions 119 class RpcException:Exception 120 { 121 RPC_ERROR_CODE code; 122 123 @safe pure nothrow this(string msg = "", string file = __FILE__, size_t line = __LINE__, Throwable next = null) 124 { 125 super(msg, file, line, next); 126 } 127 128 } 129 130 class RpcParseError: RpcException 131 { 132 @safe pure nothrow this(string msg = "", string file = __FILE__, size_t line = __LINE__) 133 { 134 code = RPC_ERROR_CODE.PARSE_ERROR; 135 136 msg = "Parse error. " ~ msg; 137 138 super(msg, file, line); 139 } 140 } 141 142 class RpcInvalidRequest: RpcException 143 { 144 @safe pure nothrow this(string msg = "", string file = __FILE__, size_t line = __LINE__) 145 { 146 code = RPC_ERROR_CODE.INVALID_REQUEST; 147 148 msg = "Invalid request. " ~ msg; 149 150 super(msg, file, line); 151 } 152 } 153 154 class RpcMethodNotFound: RpcException 155 { 156 @safe pure nothrow this(string msg = "", string file = __FILE__, size_t line = __LINE__) 157 { 158 code = RPC_ERROR_CODE.METHOD_NOT_FOUND; 159 160 msg = "Method not found. " ~ msg; 161 162 super(msg, file, line); 163 } 164 } 165 166 class RpcInvalidParams: RpcException 167 { 168 @safe pure nothrow this(string msg = "", string file = __FILE__, size_t line = __LINE__) 169 { 170 code = RPC_ERROR_CODE.INVALID_PARAMS; 171 172 msg = "Invalid params. " ~ msg; 173 174 super(msg, file, line); 175 } 176 } 177 178 class RpcInternalError: RpcException 179 { 180 @safe pure nothrow this(string msg = "", string file = __FILE__, size_t line = __LINE__) 181 { 182 code = RPC_ERROR_CODE.INTERNAL_ERROR; 183 184 msg = "Internal error. " ~ msg; 185 186 super(msg, file, line); 187 } 188 } 189 190 class RpcServerError: RpcException 191 { 192 @safe pure nothrow this(string msg = "", string file = __FILE__, size_t line = __LINE__) 193 { 194 code = RPC_ERROR_CODE.SERVER_ERROR; 195 196 msg = "Server error. " ~ msg; 197 198 super(msg, file, line); 199 } 200 } 201 202 unittest 203 { 204 import vibe.data.bson; 205 import vibe.data.json; 206 207 auto code = cast(int) RPC_ERROR_CODE.METHOD_NOT_FOUND; 208 auto message = "METHOD NOT FOUND"; 209 210 auto error1 = RpcError(Bson(["code":Bson(code),"message": Bson(message)])).toJson(); 211 212 auto error2 = RpcError(cast(RPC_ERROR_CODE)code, message).toJson(); 213 214 auto error = Json.emptyObject; 215 error.code = code; 216 error.message = message; 217 218 assert(error == error1, "RpcError unittest failed"); 219 assert(error == error2, "RpcError unittest failed"); 220 }