From 11a45d35086b3a5be2701dbe08d6c130cfb01433 Mon Sep 17 00:00:00 2001 From: badaix Date: Sun, 6 Sep 2015 22:15:55 +0200 Subject: [PATCH] cleaned up json rpc exceptions --- server/json/jsonrpc.cpp | 20 +++-- server/json/jsonrpc.h | 96 +--------------------- server/json/jsonrpcException.h | 140 +++++++++++++++++++++++++++++++++ testClient.py | 10 +++ 4 files changed, 165 insertions(+), 101 deletions(-) create mode 100644 server/json/jsonrpcException.h diff --git a/server/json/jsonrpc.cpp b/server/json/jsonrpc.cpp index cec0ed54..fc107e84 100644 --- a/server/json/jsonrpc.cpp +++ b/server/json/jsonrpc.cpp @@ -50,15 +50,23 @@ void JsonRequest::parse(const std::string& json) throw JsonRequestException(e.what(), -32700); } + if (json_.count("id") == 0) + throw JsonInvalidRequestException("id is missing", -1); id = json_["id"].get(); + if (id < 0) + throw JsonInvalidRequestException("id must be a positive integer", id); + + if (json_.count("jsonrpc") == 0) + throw JsonInvalidRequestException("jsonrpc is missing", id); string jsonrpc = json_["jsonrpc"].get(); if (jsonrpc != "2.0") - throw JsonRequestException("invalid jsonrpc value: " + jsonrpc, -32600); + throw JsonInvalidRequestException("invalid jsonrpc value: " + jsonrpc, id); + + if (json_.count("method") == 0) + throw JsonInvalidRequestException("method is missing", id); method = json_["method"].get(); if (method.empty()) - throw JsonRequestException("method must not be empty", -32600); - if (id < 0) - throw JsonRequestException("id must be a positive integer", -32600); + throw JsonInvalidRequestException("method must not be empty", id); params.clear(); try @@ -72,7 +80,7 @@ void JsonRequest::parse(const std::string& json) } catch (const exception& e) { - throw JsonRequestException(e.what(), -32602); + throw JsonInvalidParamsException(e.what(), id); } } catch (const JsonRequestException& e) @@ -81,7 +89,7 @@ void JsonRequest::parse(const std::string& json) } catch (const exception& e) { - throw JsonRequestException(e.what(), -32603, id); + throw JsonInternalErrorException(e.what(), id); } } diff --git a/server/json/jsonrpc.h b/server/json/jsonrpc.h index 7c255e17..b46402e2 100644 --- a/server/json/jsonrpc.h +++ b/server/json/jsonrpc.h @@ -23,107 +23,13 @@ #include #include #include "json.hpp" -#include "common/snapException.h" +#include "jsonrpcException.h" using Json = nlohmann::json; -class JsonRequestException : public SnapException -{ - int errorCode_, id_; -public: - JsonRequestException(const char* text, int errorCode = 0, int requestId = -1) : SnapException(text), errorCode_(errorCode), id_(requestId) - { - } - - JsonRequestException(const std::string& text, int errorCode = 0, int requestId = -1) : SnapException(text), errorCode_(errorCode), id_(requestId) - { - } - -// JsonRequestException(const JsonRequest& request, const std::string& text, int errorCode = 0) : SnapException(text), errorCode_(errorCode), id_(request.id) -// { -// } - - JsonRequestException(const JsonRequestException& e) : SnapException(e.what()), errorCode_(e.errorCode()), id_(e.id_) - { - } - - virtual int errorCode() const noexcept - { - return errorCode_; - } - - Json getResponse() const noexcept - { - int errorCode = errorCode_; - if (errorCode == 0) - errorCode = -32603; - - Json response = { - {"jsonrpc", "2.0"}, - {"error", { - {"code", errorCode}, - {"message", what()} - }}, - }; - if (id_ == -1) - response["id"] = nullptr; - else - response["id"] = id_; - - return response; - } -}; - - -// -32601 Method not found The method does not exist / is not available. -// -32602 Invalid params Invalid method parameter(s). -// -32603 Internal error Internal JSON-RPC error. - -class JsonMethodNotFoundException : public JsonRequestException -{ -public: - JsonMethodNotFoundException(int requestId = -1) : JsonRequestException("method not found", -32601, requestId) - { - } - - JsonMethodNotFoundException(const std::string& message, int requestId = -1) : JsonRequestException(message, -32601, requestId) - { - } -}; - - - -class JsonInvalidParamsException : public JsonRequestException -{ -public: - JsonInvalidParamsException(int requestId = -1) : JsonRequestException("invalid params", -32602, requestId) - { - } - - JsonInvalidParamsException(const std::string& message, int requestId = -1) : JsonRequestException(message, -32602, requestId) - { - } -}; - - -class JsonInternalErrorException : public JsonRequestException -{ -public: - JsonInternalErrorException(int requestId = -1) : JsonRequestException("internal error", -32603, requestId) - { - } - - JsonInternalErrorException(const std::string& message, int requestId = -1) : JsonRequestException(message, -32603, requestId) - { - } -}; - - - - /// JSON-RPC 2.0 request /** * Simple jsonrpc 2.0 parser with getters diff --git a/server/json/jsonrpcException.h b/server/json/jsonrpcException.h new file mode 100644 index 00000000..3b8687b9 --- /dev/null +++ b/server/json/jsonrpcException.h @@ -0,0 +1,140 @@ +/*** + This file is part of snapcast + Copyright (C) 2015 Johannes Pohl + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***/ + +#ifndef JSON_RPC_EXCEPTION_H +#define JSON_RPC_EXCEPTION_H + +#include +#include +#include "json.hpp" +#include "common/snapException.h" + + +using Json = nlohmann::json; + + + +class JsonRequestException : public SnapException +{ + int errorCode_, id_; +public: + JsonRequestException(const char* text, int errorCode = 0, int requestId = -1) : SnapException(text), errorCode_(errorCode), id_(requestId) + { + } + + JsonRequestException(const std::string& text, int errorCode = 0, int requestId = -1) : SnapException(text), errorCode_(errorCode), id_(requestId) + { + } + +// JsonRequestException(const JsonRequest& request, const std::string& text, int errorCode = 0) : SnapException(text), errorCode_(errorCode), id_(request.id) +// { +// } + + JsonRequestException(const JsonRequestException& e) : SnapException(e.what()), errorCode_(e.errorCode()), id_(e.id_) + { + } + + virtual int errorCode() const noexcept + { + return errorCode_; + } + + Json getResponse() const noexcept + { + int errorCode = errorCode_; + if (errorCode == 0) + errorCode = -32603; + + Json response = { + {"jsonrpc", "2.0"}, + {"error", { + {"code", errorCode}, + {"message", what()} + }}, + }; + if (id_ == -1) + response["id"] = nullptr; + else + response["id"] = id_; + + return response; + } +}; + + +// -32600 Invalid Request The JSON sent is not a valid Request object. +// -32601 Method not found The method does not exist / is not available. +// -32602 Invalid params Invalid method parameter(s). +// -32603 Internal error Internal JSON-RPC error. + +class JsonInvalidRequestException : public JsonRequestException +{ +public: + JsonInvalidRequestException(int requestId = -1) : JsonRequestException("invalid request", -32600, requestId) + { + } + + JsonInvalidRequestException(const std::string& message, int requestId = -1) : JsonRequestException(message, -32600, requestId) + { + } +}; + + + +class JsonMethodNotFoundException : public JsonRequestException +{ +public: + JsonMethodNotFoundException(int requestId = -1) : JsonRequestException("method not found", -32601, requestId) + { + } + + JsonMethodNotFoundException(const std::string& message, int requestId = -1) : JsonRequestException(message, -32601, requestId) + { + } +}; + + + +class JsonInvalidParamsException : public JsonRequestException +{ +public: + JsonInvalidParamsException(int requestId = -1) : JsonRequestException("invalid params", -32602, requestId) + { + } + + JsonInvalidParamsException(const std::string& message, int requestId = -1) : JsonRequestException(message, -32602, requestId) + { + } +}; + + +class JsonInternalErrorException : public JsonRequestException +{ +public: + JsonInternalErrorException(int requestId = -1) : JsonRequestException("internal error", -32603, requestId) + { + } + + JsonInternalErrorException(const std::string& message, int requestId = -1) : JsonRequestException(message, -32603, requestId) + { + } +}; + + +#endif + diff --git a/testClient.py b/testClient.py index f24a298a..9094c27d 100755 --- a/testClient.py +++ b/testClient.py @@ -48,6 +48,16 @@ doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetMute\", \"params\": {\ doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetMute\", \"params\": {\"client\": \"00:21:6a:7d:74:fc\", \"mute\": false}, \"id\": 9}\r\n") doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetLatency\", \"params\": {\"client\": \"00:21:6a:7d:74:fc\", \"latency\": 10}, \"id\": 7}\r\n") doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetName\", \"params\": {\"client\": \"00:21:6a:7d:74:fc\", \"name\": \"living room\"}, \"id\": 8}\r\n") +#invalid json +doRequest("some message to test invalid requests\r\n") +#missing id +doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetName\", \"params\": {\"client\": \"00:21:6a:7d:74:fc\", \"name\": \"living room\"}}\r\n") +#missing parameter +doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetName\", \"params\": {\"client\": \"00:21:6a:7d:74:fc\"}, \"id\": 8}\r\n") +#invalid method +doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"NonExistingMethod\", \"params\": {\"client\": \"00:21:6a:7d:74:fc\"}, \"id\": 8}\r\n") +#out of range +doRequest("{\"jsonrpc\": \"2.0\", \"method\": \"Client.SetVolume\", \"params\": {\"client\": \"00:21:6a:7d:74:fc\", \"volume\": 101}, \"id\": 3}\r\n") s = raw_input("") print(s)