diff --git a/src/rpc/RPC.cpp b/src/rpc/RPC.cpp index 99ce33b2..e350b91f 100644 --- a/src/rpc/RPC.cpp +++ b/src/rpc/RPC.cpp @@ -91,6 +91,38 @@ make_HttpContext( clientIp}; } +constexpr static WarningInfo warningInfos[]{ + {warnUNKNOWN, "Unknown warning"}, + {warnRPC_CLIO, + "This is a clio server. clio only serves validated data. If you " + "want to talk to rippled, include 'ledger_index':'current' in your " + "request"}, + {warnRPC_OUTDATED, "This server may be out of date"}, + {warnRPC_RATE_LIMIT, "You are about to be rate limited"}}; + +WarningInfo const& +get_warning_info(warning_code code) +{ + for (WarningInfo const& info : warningInfos) + { + if (info.code == code) + { + return info; + } + } + throw(std::out_of_range("Invalid warning_code")); +} + +boost::json::object +make_warning(warning_code code) +{ + boost::json::object json; + WarningInfo const& info(get_warning_info(code)); + json["id"] = code; + json["message"] = static_cast(info.message); + return json; +} + boost::json::object make_error(Error err) { diff --git a/src/rpc/RPC.h b/src/rpc/RPC.h index 9af45424..29154734 100644 --- a/src/rpc/RPC.h +++ b/src/rpc/RPC.h @@ -162,6 +162,33 @@ public: } }; +enum warning_code { + warnUNKNOWN = -1, + warnRPC_CLIO = 2001, + warnRPC_OUTDATED = 2002, + warnRPC_RATE_LIMIT = 2003 +}; + +struct WarningInfo +{ + constexpr WarningInfo() : code(warnUNKNOWN), message("unknown warning") + { + } + + constexpr WarningInfo(warning_code code_, char const* message_) + : code(code_), message(message_) + { + } + warning_code code; + std::string_view const message; +}; + +WarningInfo const& +get_warning_info(warning_code code); + +boost::json::object +make_warning(warning_code code); + boost::json::object make_error(Status const& status); diff --git a/src/webserver/HttpBase.h b/src/webserver/HttpBase.h index e94ee29b..51ae9efa 100644 --- a/src/webserver/HttpBase.h +++ b/src/webserver/HttpBase.h @@ -417,18 +417,17 @@ handle_request( } boost::json::array warnings; - warnings.emplace_back( - "This is a clio server. clio only serves validated data. If you " - "want to talk to rippled, include 'ledger_index':'current' in your " - "request"); + warnings.emplace_back(RPC::make_warning(RPC::warnRPC_CLIO)); auto lastCloseAge = context->etl->lastCloseAgeSeconds(); if (lastCloseAge >= 60) - warnings.emplace_back("This server may be out of date"); + warnings.emplace_back(RPC::make_warning(RPC::warnRPC_OUTDATED)); response["warnings"] = warnings; responseStr = boost::json::serialize(response); if (!dosGuard.add(ip, responseStr.size())) { response["warning"] = "load"; + warnings.emplace_back(RPC::make_warning(RPC::warnRPC_RATE_LIMIT)); + response["warnings"] = warnings; // reserialize when we need to include this warning responseStr = boost::json::serialize(response); } diff --git a/src/webserver/WsBase.h b/src/webserver/WsBase.h index a058ecaa..6342ab21 100644 --- a/src/webserver/WsBase.h +++ b/src/webserver/WsBase.h @@ -330,19 +330,19 @@ public: } boost::json::array warnings; - warnings.emplace_back( - "This is a clio server. clio only serves validated data. If you " - "want to talk to rippled, include 'ledger_index':'current' in your " - "request"); + + warnings.emplace_back(RPC::make_warning(RPC::warnRPC_CLIO)); auto lastCloseAge = etl_->lastCloseAgeSeconds(); if (lastCloseAge >= 60) - warnings.emplace_back("This server may be out of date"); + warnings.emplace_back(RPC::make_warning(RPC::warnRPC_OUTDATED)); response["warnings"] = warnings; std::string responseStr = boost::json::serialize(response); if (!dosGuard_.add(*ip, responseStr.size())) { response["warning"] = "load"; + warnings.emplace_back(RPC::make_warning(RPC::warnRPC_RATE_LIMIT)); + response["warnings"] = warnings; // reserialize if we need to include this warning responseStr = boost::json::serialize(response); }