mirror of
https://github.com/XRPLF/clio.git
synced 2026-09-28 07:58:10 +00:00
Use errors from rpcspec
This commit is contained in:
11
src/etl/Errors.hpp
Normal file
11
src/etl/Errors.hpp
Normal file
@@ -0,0 +1,11 @@
|
||||
/** @file */
|
||||
#pragma once
|
||||
|
||||
#include <rpcspec/Errors.hpp>
|
||||
|
||||
namespace etl {
|
||||
|
||||
/** @brief Error codes produced by ETL source operations. Aliased from rpc::EtlError. */
|
||||
using EtlError = rpc::EtlError;
|
||||
|
||||
} // namespace etl
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "etl/LoadBalancer.hpp"
|
||||
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
#include "etl/ETLState.hpp"
|
||||
#include "etl/InitialLoadObserverInterface.hpp"
|
||||
#include "etl/LoadBalancerInterface.hpp"
|
||||
@@ -292,7 +293,7 @@ LoadBalancer::forwardToRippled(
|
||||
auto xUserValue = isAdmin ? kAdminForwardingXUserValue : kUserForwardingXUserValue;
|
||||
|
||||
std::optional<boost::json::object> response;
|
||||
rpc::ClioError error = rpc::ClioError::EtlConnectionError;
|
||||
etl::EtlError error = etl::EtlError::ConnectionError;
|
||||
while (numAttempts < sources_.size()) {
|
||||
auto [res, duration] = util::timed([&]() {
|
||||
return sources_[sourceIdx]->forwardToRippled(request, clientIp, xUserValue, yield);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "etl/LoadBalancerInterface.hpp"
|
||||
#include "etl/NetworkValidatedLedgersInterface.hpp"
|
||||
#include "feed/SubscriptionManagerInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
#include "util/config/ObjectView.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
@@ -131,7 +131,7 @@ public:
|
||||
* @param yield The coroutine context
|
||||
* @return Response on success or error on failure
|
||||
*/
|
||||
[[nodiscard]] virtual std::expected<boost::json::object, rpc::ClioError>
|
||||
[[nodiscard]] virtual std::expected<boost::json::object, etl::EtlError>
|
||||
forwardToRippled(
|
||||
boost::json::object const& request,
|
||||
std::optional<std::string> const& forwardToRippledClientIp,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "etl/impl/ForwardingSource.hpp"
|
||||
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
@@ -38,7 +38,7 @@ ForwardingSource::ForwardingSource(
|
||||
);
|
||||
}
|
||||
|
||||
std::expected<boost::json::object, rpc::ClioError>
|
||||
std::expected<boost::json::object, EtlError>
|
||||
ForwardingSource::forwardToRippled(
|
||||
boost::json::object const& request,
|
||||
std::optional<std::string> const& forwardToRippledClientIp,
|
||||
@@ -58,14 +58,14 @@ ForwardingSource::forwardToRippled(
|
||||
auto expectedConnection = connectionBuilder.connect(yield);
|
||||
if (not expectedConnection) {
|
||||
LOG(log_.debug()) << "Couldn't connect to rippled to forward request.";
|
||||
return std::unexpected{rpc::ClioError::EtlConnectionError};
|
||||
return std::unexpected{EtlError::ConnectionError};
|
||||
}
|
||||
auto& connection = expectedConnection.value();
|
||||
|
||||
auto writeError = connection->write(boost::json::serialize(request), yield, forwardingTimeout_);
|
||||
if (writeError) {
|
||||
LOG(log_.debug()) << "Error sending request to rippled to forward request.";
|
||||
return std::unexpected{rpc::ClioError::EtlRequestError};
|
||||
return std::unexpected{EtlError::RequestError};
|
||||
}
|
||||
|
||||
auto response = connection->read(yield, forwardingTimeout_);
|
||||
@@ -73,10 +73,10 @@ ForwardingSource::forwardToRippled(
|
||||
if (auto errorCode = response.error().errorCode();
|
||||
errorCode.has_value() and errorCode->value() == boost::system::errc::timed_out) {
|
||||
LOG(log_.debug()) << "Request to rippled timed out";
|
||||
return std::unexpected{rpc::ClioError::EtlRequestTimeout};
|
||||
return std::unexpected{EtlError::RequestTimeout};
|
||||
}
|
||||
LOG(log_.debug()) << "Error sending request to rippled to forward request.";
|
||||
return std::unexpected{rpc::ClioError::EtlRequestError};
|
||||
return std::unexpected{EtlError::RequestError};
|
||||
}
|
||||
|
||||
boost::json::value parsedResponse;
|
||||
@@ -87,7 +87,7 @@ ForwardingSource::forwardToRippled(
|
||||
} catch (std::exception const& e) {
|
||||
LOG(log_.debug()) << "Error parsing response from rippled: " << e.what()
|
||||
<< ". Response: " << *response;
|
||||
return std::unexpected{rpc::ClioError::EtlInvalidResponse};
|
||||
return std::unexpected{EtlError::InvalidResponse};
|
||||
}
|
||||
|
||||
auto responseObject = parsedResponse.as_object();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "util/requests/WsConnection.hpp"
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
* @param yield The coroutine context
|
||||
* @return Response on success or error on failure
|
||||
*/
|
||||
[[nodiscard]] std::expected<boost::json::object, rpc::ClioError>
|
||||
[[nodiscard]] std::expected<boost::json::object, EtlError>
|
||||
forwardToRippled(
|
||||
boost::json::object const& request,
|
||||
std::optional<std::string> const& forwardToRippledClientIp,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "etl/impl/ForwardingSource.hpp"
|
||||
#include "etl/impl/GrpcSource.hpp"
|
||||
#include "etl/impl/SubscriptionSource.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
@@ -208,9 +208,9 @@ public:
|
||||
* @param forwardToRippledClientIp IP of the client forwarding this request if known
|
||||
* @param xUserValue Optional value of the X-User header
|
||||
* @param yield The coroutine context
|
||||
* @return Response or ClioError
|
||||
* @return Response or EtlError
|
||||
*/
|
||||
[[nodiscard]] std::expected<boost::json::object, rpc::ClioError>
|
||||
[[nodiscard]] std::expected<boost::json::object, etl::EtlError>
|
||||
forwardToRippled(
|
||||
boost::json::object const& request,
|
||||
std::optional<std::string> const& forwardToRippledClientIp,
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
#include "util/OverloadSet.hpp"
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <rpcspec/Errors.hpp>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
@@ -46,6 +48,16 @@ operator<<(std::ostream& stream, Status const& status)
|
||||
} else {
|
||||
stream << ", Message: " << getErrorInfo(err).message;
|
||||
}
|
||||
},
|
||||
[&stream, &status](EtlError err) {
|
||||
stream << "Code: " << static_cast<std::underlying_type_t<EtlError>>(err);
|
||||
if (!status.error.empty())
|
||||
stream << ", Error: " << status.error;
|
||||
if (!status.message.empty()) {
|
||||
stream << ", Message: " << status.message;
|
||||
} else {
|
||||
stream << ", Message: " << getEtlErrorInfo(err).message;
|
||||
}
|
||||
}
|
||||
},
|
||||
status.code
|
||||
@@ -57,100 +69,111 @@ operator<<(std::ostream& stream, Status const& status)
|
||||
return stream;
|
||||
}
|
||||
|
||||
WarningInfo const&
|
||||
getWarningInfo(WarningCode code)
|
||||
EtlErrorInfo const&
|
||||
getEtlErrorInfo(EtlError code)
|
||||
{
|
||||
static constexpr WarningInfo kInfos[]{
|
||||
{WarningCode::WarnUnknown, "Unknown warning"},
|
||||
{WarningCode::WarnRpcClio,
|
||||
"This is a clio server. clio only serves validated data. If you want to talk to rippled, "
|
||||
"include "
|
||||
"'ledger_index':'current' in your request"},
|
||||
{WarningCode::WarnRpcOutdated, "This server may be out of date"},
|
||||
{WarningCode::WarnRpcRateLimit, "You are about to be rate limited"},
|
||||
{WarningCode::WarnRpcDeprecated,
|
||||
"Some fields from your request are deprecated. Please check the documentation at "
|
||||
"https://xrpl.org/docs/references/http-websocket-apis/ and update your request."}
|
||||
};
|
||||
static constexpr auto kInfos = std::to_array<EtlErrorInfo>({
|
||||
{
|
||||
.code = EtlError::ConnectionError,
|
||||
.error = "connectionError",
|
||||
.message = "Couldn't connect to rippled.",
|
||||
},
|
||||
{
|
||||
.code = EtlError::RequestError,
|
||||
.error = "requestError",
|
||||
.message = "Error sending request to rippled.",
|
||||
},
|
||||
{
|
||||
.code = EtlError::RequestTimeout,
|
||||
.error = "timeout",
|
||||
.message = "Request to rippled timed out.",
|
||||
},
|
||||
{
|
||||
.code = EtlError::InvalidResponse,
|
||||
.error = "invalidResponse",
|
||||
.message = "Rippled returned an invalid response.",
|
||||
},
|
||||
});
|
||||
|
||||
auto matchByCode = [code](auto const& info) { return info.code == code; };
|
||||
if (auto it = ranges::find_if(kInfos, matchByCode); it != end(kInfos))
|
||||
if (auto it = ranges::find(kInfos, code, &EtlErrorInfo::code); it != end(kInfos))
|
||||
return *it;
|
||||
|
||||
throw(out_of_range("Invalid WarningCode"));
|
||||
}
|
||||
|
||||
boost::json::object
|
||||
makeWarning(WarningCode code)
|
||||
{
|
||||
auto json = boost::json::object{};
|
||||
auto const& info = getWarningInfo(code);
|
||||
json["id"] = static_cast<int>(code);
|
||||
json["message"] = info.message;
|
||||
return json;
|
||||
throw(out_of_range("Invalid EtlError code"));
|
||||
}
|
||||
|
||||
ClioErrorInfo const&
|
||||
getErrorInfo(ClioError code)
|
||||
{
|
||||
static constexpr ClioErrorInfo kInfos[]{
|
||||
{.code = ClioError::RpcMalformedCurrency,
|
||||
.error = "malformedCurrency",
|
||||
.message = "Malformed currency."},
|
||||
{.code = ClioError::RpcMalformedRequest,
|
||||
.error = "malformedRequest",
|
||||
.message = "Malformed request."},
|
||||
{.code = ClioError::RpcMalformedOwner,
|
||||
.error = "malformedOwner",
|
||||
.message = "Malformed owner."},
|
||||
{.code = ClioError::RpcMalformedAddress,
|
||||
.error = "malformedAddress",
|
||||
.message = "Malformed address."},
|
||||
{.code = ClioError::RpcUnknownOption,
|
||||
.error = "unknownOption",
|
||||
.message = "Unknown option."},
|
||||
{.code = ClioError::RpcFieldNotFoundTransaction,
|
||||
.error = "fieldNotFoundTransaction",
|
||||
.message = "Missing field."},
|
||||
{.code = ClioError::RpcMalformedOracleDocumentId,
|
||||
.error = "malformedDocumentID",
|
||||
.message = "Malformed oracle_document_id."},
|
||||
{.code = ClioError::RpcMalformedAuthorizedCredentials,
|
||||
.error = "malformedAuthorizedCredentials",
|
||||
.message = "Malformed authorized credentials."},
|
||||
static constexpr auto kInfos = std::to_array<ClioErrorInfo>({
|
||||
{
|
||||
.code = ClioError::RpcMalformedCurrency,
|
||||
.error = "malformedCurrency",
|
||||
.message = "Malformed currency.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcMalformedRequest,
|
||||
.error = "malformedRequest",
|
||||
.message = "Malformed request.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcMalformedOwner,
|
||||
.error = "malformedOwner",
|
||||
.message = "Malformed owner.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcMalformedAddress,
|
||||
.error = "malformedAddress",
|
||||
.message = "Malformed address.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcUnknownOption,
|
||||
.error = "unknownOption",
|
||||
.message = "Unknown option.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcFieldNotFoundTransaction,
|
||||
.error = "fieldNotFoundTransaction",
|
||||
.message = "Missing field.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcMalformedOracleDocumentId,
|
||||
.error = "malformedDocumentID",
|
||||
.message = "Malformed oracle_document_id.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcMalformedAuthorizedCredentials,
|
||||
.error = "malformedAuthorizedCredentials",
|
||||
.message = "Malformed authorized credentials.",
|
||||
},
|
||||
// special system errors
|
||||
{.code = ClioError::RpcInvalidApiVersion,
|
||||
.error = JS(invalid_API_version),
|
||||
.message = "Invalid API version."},
|
||||
{.code = ClioError::RpcCommandIsMissing,
|
||||
.error = JS(missingCommand),
|
||||
.message = "Method is not specified or is not a string."},
|
||||
{.code = ClioError::RpcCommandNotString,
|
||||
.error = "commandNotString",
|
||||
.message = "Method is not a string."},
|
||||
{.code = ClioError::RpcCommandIsEmpty,
|
||||
.error = "emptyCommand",
|
||||
.message = "Method is an empty string."},
|
||||
{.code = ClioError::RpcParamsUnparsable,
|
||||
.error = "paramsUnparsable",
|
||||
.message = "Params must be an array holding exactly one object."},
|
||||
// etl related errors
|
||||
{.code = ClioError::EtlConnectionError,
|
||||
.error = "connectionError",
|
||||
.message = "Couldn't connect to rippled."},
|
||||
{.code = ClioError::EtlRequestError,
|
||||
.error = "requestError",
|
||||
.message = "Error sending request to rippled."},
|
||||
{.code = ClioError::EtlRequestTimeout,
|
||||
.error = "timeout",
|
||||
.message = "Request to rippled timed out."},
|
||||
{.code = ClioError::EtlInvalidResponse,
|
||||
.error = "invalidResponse",
|
||||
.message = "Rippled returned an invalid response."}
|
||||
};
|
||||
{
|
||||
.code = ClioError::RpcInvalidApiVersion,
|
||||
.error = JS(invalid_API_version),
|
||||
.message = "Invalid API version.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcCommandIsMissing,
|
||||
.error = JS(missingCommand),
|
||||
.message = "Method is not specified or is not a string.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcCommandNotString,
|
||||
.error = "commandNotString",
|
||||
.message = "Method is not a string.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcCommandIsEmpty,
|
||||
.error = "emptyCommand",
|
||||
.message = "Method is an empty string.",
|
||||
},
|
||||
{
|
||||
.code = ClioError::RpcParamsUnparsable,
|
||||
.error = "paramsUnparsable",
|
||||
.message = "Params must be an array holding exactly one object.",
|
||||
},
|
||||
});
|
||||
|
||||
auto matchByCode = [code](auto const& info) { return info.code == code; };
|
||||
if (auto it = ranges::find_if(kInfos, matchByCode); it != end(kInfos))
|
||||
if (auto it = ranges::find(kInfos, code, &ClioErrorInfo::code); it != end(kInfos))
|
||||
return *it;
|
||||
|
||||
throw(out_of_range("Invalid error code"));
|
||||
@@ -215,6 +238,16 @@ makeError(Status const& status)
|
||||
[&status, &wrapOptional](ClioError err) {
|
||||
return makeError(err, wrapOptional(status.error), wrapOptional(status.message));
|
||||
},
|
||||
[](EtlError err) {
|
||||
auto const& info = getEtlErrorInfo(err);
|
||||
return boost::json::object{
|
||||
{"error", info.error},
|
||||
{"error_code", static_cast<uint32_t>(err)},
|
||||
{"error_message", info.message},
|
||||
{"status", "error"},
|
||||
{"type", "response"}
|
||||
};
|
||||
},
|
||||
},
|
||||
status.code
|
||||
);
|
||||
|
||||
@@ -2,49 +2,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <rpcspec/Errors.hpp>
|
||||
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
/**
|
||||
* @brief Custom clio RPC Errors.
|
||||
*/
|
||||
enum class ClioError {
|
||||
// normal clio errors start with 5000
|
||||
RpcMalformedCurrency = 5000,
|
||||
RpcMalformedRequest = 5001,
|
||||
RpcMalformedOwner = 5002,
|
||||
RpcMalformedAddress = 5003,
|
||||
RpcUnknownOption = 5005,
|
||||
RpcFieldNotFoundTransaction = 5006,
|
||||
RpcMalformedOracleDocumentId = 5007,
|
||||
RpcMalformedAuthorizedCredentials = 5008,
|
||||
// NOTE: RpcEntryNotFound is replaced with RippledError::RpcEntryNotFound
|
||||
// RpcEntryNotFound = 5009,
|
||||
|
||||
// special system errors start with 6000
|
||||
RpcInvalidApiVersion = 6000,
|
||||
RpcCommandIsMissing = 6001,
|
||||
RpcCommandNotString = 6002,
|
||||
RpcCommandIsEmpty = 6003,
|
||||
RpcParamsUnparsable = 6004,
|
||||
|
||||
// TODO: Since it is not only rpc errors here now, we should move it to util
|
||||
// etl related errors start with 7000
|
||||
// Higher value in this errors means better progress in the forwarding
|
||||
EtlConnectionError = 7000,
|
||||
EtlRequestError = 7001,
|
||||
EtlRequestTimeout = 7002,
|
||||
EtlInvalidResponse = 7003,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Holds info about a particular @ref ClioError.
|
||||
*/
|
||||
@@ -55,166 +22,12 @@ struct ClioErrorInfo {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Clio uses compatible Rippled error codes for most RPC errors.
|
||||
* @brief Holds info about a particular @ref rpc::EtlError.
|
||||
*/
|
||||
using RippledError = xrpl::ErrorCodeI;
|
||||
|
||||
/**
|
||||
* @brief Clio operates on a combination of Rippled and Custom Clio error codes.
|
||||
*
|
||||
* @see RippledError For rippled error codes
|
||||
* @see ClioError For custom clio error codes
|
||||
*/
|
||||
using CombinedError = std::variant<RippledError, ClioError>;
|
||||
|
||||
/**
|
||||
* @brief A status returned from any RPC handler.
|
||||
*/
|
||||
struct Status {
|
||||
CombinedError code = RippledError::RpcSuccess;
|
||||
std::string error;
|
||||
std::string message;
|
||||
std::optional<boost::json::object> extraInfo;
|
||||
|
||||
Status() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new Status object
|
||||
*
|
||||
* @param code The error code
|
||||
*/
|
||||
/* implicit */ Status(CombinedError code) : code(code) {};
|
||||
|
||||
/**
|
||||
* @brief Construct a new Status object
|
||||
*
|
||||
* @param code The error code
|
||||
* @param extraInfo The extra info
|
||||
*/
|
||||
Status(CombinedError code, boost::json::object&& extraInfo)
|
||||
: code(code), extraInfo(std::move(extraInfo)) {};
|
||||
|
||||
/**
|
||||
* @brief Construct a new Status object with a custom message
|
||||
*
|
||||
* @note HACK. Some rippled handlers explicitly specify errors. This means that we have to be
|
||||
* able to duplicate this functionality.
|
||||
*
|
||||
* @param message The message
|
||||
*/
|
||||
explicit Status(std::string message) : code(xrpl::RpcUnknown), message(std::move(message))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a new Status object
|
||||
*
|
||||
* @param code The error code
|
||||
* @param message The message
|
||||
*/
|
||||
Status(CombinedError code, std::string message) : code(code), message(std::move(message))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a new Status object
|
||||
*
|
||||
* @param code The error code
|
||||
* @param error The error
|
||||
* @param message The message
|
||||
*/
|
||||
Status(CombinedError code, std::string error, std::string message)
|
||||
: code(code), error(std::move(error)), message(std::move(message))
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(Status const& other) const = default;
|
||||
|
||||
/**
|
||||
* @brief Check if the status is not OK
|
||||
*
|
||||
* @return true if the status is not OK; false otherwise
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
if (auto err = std::get_if<RippledError>(&code))
|
||||
return *err != RippledError::RpcSuccess;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the @ref rpc::Status contains the desired @ref rpc::RippledError
|
||||
*
|
||||
* @param other The @ref rpc::RippledError to match
|
||||
* @return true if status matches given error; false otherwise
|
||||
*/
|
||||
bool
|
||||
operator==(RippledError other) const
|
||||
{
|
||||
if (auto err = std::get_if<RippledError>(&code))
|
||||
return *err == other;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the Status contains the desired @ref ClioError
|
||||
*
|
||||
* @param other The RippledError to match
|
||||
* @return true if status matches given error; false otherwise
|
||||
*/
|
||||
bool
|
||||
operator==(ClioError other) const
|
||||
{
|
||||
if (auto err = std::get_if<ClioError>(&code))
|
||||
return *err == other;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Custom output stream for Status
|
||||
*
|
||||
* @param stream The output stream
|
||||
* @param status The Status
|
||||
* @return The same ostream we were given
|
||||
*/
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& stream, Status const& status);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Warning codes that can be returned by clio.
|
||||
*/
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum WarningCode {
|
||||
WarnUnknown = -1,
|
||||
WarnRpcClio = 2001,
|
||||
WarnRpcOutdated = 2002,
|
||||
WarnRpcRateLimit = 2003,
|
||||
WarnRpcDeprecated = 2004
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Holds information about a clio warning.
|
||||
*/
|
||||
struct WarningInfo {
|
||||
constexpr WarningInfo() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new Warning Info object
|
||||
*
|
||||
* @param code The warning code
|
||||
* @param message The warning message
|
||||
*/
|
||||
constexpr WarningInfo(WarningCode code, char const* message) : code(code), message(message)
|
||||
{
|
||||
}
|
||||
|
||||
WarningCode code = WarningCode::WarnUnknown;
|
||||
std::string_view const message = "unknown warning";
|
||||
struct EtlErrorInfo {
|
||||
EtlError const code;
|
||||
std::string_view const error;
|
||||
std::string_view const message;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -278,15 +91,6 @@ public:
|
||||
*/
|
||||
static Status gOk;
|
||||
|
||||
/**
|
||||
* @brief Get the warning info object from a warning code.
|
||||
*
|
||||
* @param code The warning code
|
||||
* @return A reference to the static warning info
|
||||
*/
|
||||
WarningInfo const&
|
||||
getWarningInfo(WarningCode code);
|
||||
|
||||
/**
|
||||
* @brief Get the error info object from an clio-specific error code.
|
||||
*
|
||||
@@ -297,13 +101,13 @@ ClioErrorInfo const&
|
||||
getErrorInfo(ClioError code);
|
||||
|
||||
/**
|
||||
* @brief Generate JSON from a @ref rpc::WarningCode.
|
||||
* @brief Get the ETL error info object from an ETL error code.
|
||||
*
|
||||
* @param code The warning code
|
||||
* @return The JSON output
|
||||
* @param code The error code
|
||||
* @return A reference to the static error info
|
||||
*/
|
||||
boost::json::object
|
||||
makeWarning(WarningCode code);
|
||||
EtlErrorInfo const&
|
||||
getEtlErrorInfo(EtlError code);
|
||||
|
||||
/**
|
||||
* @brief Generate JSON from a @ref rpc::Status.
|
||||
|
||||
@@ -80,15 +80,13 @@ public:
|
||||
case rpc::ClioError::RpcFieldNotFoundTransaction:
|
||||
case rpc::ClioError::RpcMalformedOracleDocumentId:
|
||||
case rpc::ClioError::RpcMalformedAuthorizedCredentials:
|
||||
case rpc::ClioError::EtlConnectionError:
|
||||
case rpc::ClioError::EtlRequestError:
|
||||
case rpc::ClioError::EtlRequestTimeout:
|
||||
case rpc::ClioError::EtlInvalidResponse:
|
||||
ASSERT(
|
||||
false, "Unknown rpc error code {}", static_cast<int>(*clioCode)
|
||||
); // this should never happen
|
||||
break;
|
||||
}
|
||||
} else if (std::get_if<rpc::EtlError>(&err.code) != nullptr) {
|
||||
ASSERT(false, "ETL error should not reach HTTP error handler"); // this should never happen
|
||||
} else {
|
||||
connection_->send(
|
||||
boost::json::serialize(composeError(err)),
|
||||
|
||||
@@ -92,15 +92,13 @@ ErrorHelper::makeError(rpc::Status const& err) const
|
||||
case rpc::ClioError::RpcFieldNotFoundTransaction:
|
||||
case rpc::ClioError::RpcMalformedOracleDocumentId:
|
||||
case rpc::ClioError::RpcMalformedAuthorizedCredentials:
|
||||
case rpc::ClioError::EtlConnectionError:
|
||||
case rpc::ClioError::EtlRequestError:
|
||||
case rpc::ClioError::EtlRequestTimeout:
|
||||
case rpc::ClioError::EtlInvalidResponse:
|
||||
ASSERT(
|
||||
false, "Unknown rpc error code {}", static_cast<int>(*clioCode)
|
||||
); // this should never happen
|
||||
break;
|
||||
}
|
||||
} else if (std::get_if<rpc::EtlError>(&err.code) != nullptr) {
|
||||
ASSERT(false, "ETL error should not reach HTTP error handler"); // this should never happen
|
||||
}
|
||||
|
||||
return Response{http::status::bad_request, composeError(err), rawRequest_};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "etl/NetworkValidatedLedgersInterface.hpp"
|
||||
#include "etl/Source.hpp"
|
||||
#include "feed/SubscriptionManagerInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
#include "util/config/ObjectView.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
@@ -50,7 +50,7 @@ struct MockSource : etl::SourceBase {
|
||||
(override)
|
||||
);
|
||||
|
||||
using ForwardToRippledReturnType = std::expected<boost::json::object, rpc::ClioError>;
|
||||
using ForwardToRippledReturnType = std::expected<boost::json::object, etl::EtlError>;
|
||||
MOCK_METHOD(
|
||||
ForwardToRippledReturnType,
|
||||
forwardToRippled,
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
return mock_->loadInitialLedger(sequence, maxLedger, observer);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::expected<boost::json::object, rpc::ClioError>
|
||||
[[nodiscard]] std::expected<boost::json::object, etl::EtlError>
|
||||
forwardToRippled(
|
||||
boost::json::object const& request,
|
||||
std::optional<std::string> const& forwardToRippledClientIp,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "etl/ETLState.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
#include "util/MockSource.hpp"
|
||||
|
||||
#include <boost/json/parse.hpp>
|
||||
@@ -18,7 +18,7 @@ struct ETLStateTest : public virtual ::testing::Test {
|
||||
TEST_F(ETLStateTest, Error)
|
||||
{
|
||||
EXPECT_CALL(source, forwardToRippled)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse}));
|
||||
.WillOnce(Return(std::unexpected{etl::EtlError::InvalidResponse}));
|
||||
auto const state = etl::ETLState::fetchETLStateFromSource(source);
|
||||
EXPECT_FALSE(state);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "etl/impl/ForwardingSource.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
#include "util/AsioContextTestFixture.hpp"
|
||||
#include "util/Spawn.hpp"
|
||||
#include "util/TestWsServer.hpp"
|
||||
@@ -35,7 +35,7 @@ TEST_F(ForwardingSourceTests, ConnectionFailed)
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
auto result = forwardingSource_.forwardToRippled({}, {}, {}, yield);
|
||||
ASSERT_FALSE(result);
|
||||
EXPECT_EQ(result.error(), rpc::ClioError::EtlConnectionError);
|
||||
EXPECT_EQ(result.error(), etl::EtlError::ConnectionError);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ TEST_F(ForwardingSourceOperationsTests, XUserHeader)
|
||||
boost::json::parse(message_).as_object(), {}, xUserValue, yield
|
||||
);
|
||||
ASSERT_FALSE(result);
|
||||
EXPECT_EQ(result.error(), rpc::ClioError::EtlRequestError);
|
||||
EXPECT_EQ(result.error(), etl::EtlError::RequestError);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ TEST_F(ForwardingSourceOperationsTests, ReadFailed)
|
||||
boost::json::parse(message_).as_object(), {}, {}, yield
|
||||
);
|
||||
ASSERT_FALSE(result);
|
||||
EXPECT_EQ(result.error(), rpc::ClioError::EtlRequestError);
|
||||
EXPECT_EQ(result.error(), etl::EtlError::RequestError);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ TEST_F(ForwardingSourceOperationsTests, ReadTimeout)
|
||||
boost::json::parse(message_).as_object(), {}, {}, yield
|
||||
);
|
||||
ASSERT_FALSE(result);
|
||||
EXPECT_EQ(result.error(), rpc::ClioError::EtlRequestTimeout);
|
||||
EXPECT_EQ(result.error(), etl::EtlError::RequestTimeout);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ TEST_F(ForwardingSourceOperationsTests, ParseFailed)
|
||||
boost::json::parse(message_).as_object(), {}, {}, yield
|
||||
);
|
||||
ASSERT_FALSE(result);
|
||||
EXPECT_EQ(result.error(), rpc::ClioError::EtlInvalidResponse);
|
||||
EXPECT_EQ(result.error(), etl::EtlError::InvalidResponse);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ TEST_F(ForwardingSourceOperationsTests, GotNotAnObject)
|
||||
boost::json::parse(message_).as_object(), {}, {}, yield
|
||||
);
|
||||
ASSERT_FALSE(result);
|
||||
EXPECT_EQ(result.error(), rpc::ClioError::EtlInvalidResponse);
|
||||
EXPECT_EQ(result.error(), etl::EtlError::InvalidResponse);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "etl/LoadBalancerInterface.hpp"
|
||||
#include "etl/Models.hpp"
|
||||
#include "etl/Source.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "util/AsioContextTestFixture.hpp"
|
||||
#include "util/MockBackendTestFixture.hpp"
|
||||
@@ -203,9 +204,9 @@ TEST_F(LoadBalancerConstructorTests, fetchETLState_AllSourcesFail)
|
||||
{
|
||||
EXPECT_CALL(sourceFactory_, makeSource).Times(2);
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError}));
|
||||
.WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError}));
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError}));
|
||||
.WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError}));
|
||||
EXPECT_THROW({ makeLoadBalancer(); }, std::logic_error);
|
||||
}
|
||||
|
||||
@@ -225,7 +226,7 @@ TEST_F(LoadBalancerConstructorTests, fetchETLState_Source1Fails0OK)
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled)
|
||||
.WillOnce(Return(boost::json::object{}));
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError}));
|
||||
.WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError}));
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(1), run);
|
||||
makeLoadBalancer();
|
||||
@@ -235,7 +236,7 @@ TEST_F(LoadBalancerConstructorTests, fetchETLState_Source0Fails1OK)
|
||||
{
|
||||
EXPECT_CALL(sourceFactory_, makeSource).Times(2);
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError}));
|
||||
.WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError}));
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled)
|
||||
.WillOnce(Return(boost::json::object{}));
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
|
||||
@@ -265,7 +266,7 @@ TEST_F(LoadBalancerConstructorTests, fetchETLState_AllSourcesFailButAllowNoEtlIs
|
||||
.WillOnce(Return(boost::json::object{}));
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError}));
|
||||
.WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError}));
|
||||
EXPECT_CALL(sourceFactory_.sourceAt(1), run);
|
||||
|
||||
configJson_.as_object()["allow_no_etl"] = true;
|
||||
@@ -716,7 +717,7 @@ TEST_F(LoadBalancerForwardToRippledTests, source0Fails)
|
||||
sourceFactory_.sourceAt(0),
|
||||
forwardToRippled(request_, clientIP_, LoadBalancer::kUserForwardingXUserValue, testing::_)
|
||||
)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError}));
|
||||
.WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError}));
|
||||
EXPECT_CALL(
|
||||
sourceFactory_.sourceAt(1),
|
||||
forwardToRippled(request_, clientIP_, LoadBalancer::kUserForwardingXUserValue, testing::_)
|
||||
@@ -819,7 +820,7 @@ TEST_F(LoadBalancerForwardToRippledPrometheusTests, source0Fails)
|
||||
sourceFactory_.sourceAt(0),
|
||||
forwardToRippled(request_, clientIP_, LoadBalancer::kUserForwardingXUserValue, testing::_)
|
||||
)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError}));
|
||||
.WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError}));
|
||||
EXPECT_CALL(
|
||||
sourceFactory_.sourceAt(1),
|
||||
forwardToRippled(request_, clientIP_, LoadBalancer::kUserForwardingXUserValue, testing::_)
|
||||
@@ -861,8 +862,8 @@ TEST_F(LoadBalancerForwardToRippledPrometheusTests, adminRequestAlwaysCacheMiss)
|
||||
|
||||
struct LoadBalancerForwardToRippledErrorTestBundle {
|
||||
std::string testName;
|
||||
rpc::ClioError firstSourceError;
|
||||
rpc::ClioError secondSourceError;
|
||||
etl::EtlError firstSourceError;
|
||||
etl::EtlError secondSourceError;
|
||||
rpc::CombinedError responseExpectedError;
|
||||
};
|
||||
|
||||
@@ -876,33 +877,33 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
testing::Values(
|
||||
LoadBalancerForwardToRippledErrorTestBundle{
|
||||
"ConnectionError_RequestError",
|
||||
rpc::ClioError::EtlConnectionError,
|
||||
rpc::ClioError::EtlRequestError,
|
||||
rpc::ClioError::EtlRequestError
|
||||
etl::EtlError::ConnectionError,
|
||||
etl::EtlError::RequestError,
|
||||
etl::EtlError::RequestError
|
||||
},
|
||||
LoadBalancerForwardToRippledErrorTestBundle{
|
||||
"RequestError_RequestTimeout",
|
||||
rpc::ClioError::EtlRequestError,
|
||||
rpc::ClioError::EtlRequestTimeout,
|
||||
rpc::ClioError::EtlRequestTimeout
|
||||
etl::EtlError::RequestError,
|
||||
etl::EtlError::RequestTimeout,
|
||||
etl::EtlError::RequestTimeout
|
||||
},
|
||||
LoadBalancerForwardToRippledErrorTestBundle{
|
||||
"RequestTimeout_InvalidResponse",
|
||||
rpc::ClioError::EtlRequestTimeout,
|
||||
rpc::ClioError::EtlInvalidResponse,
|
||||
rpc::ClioError::EtlInvalidResponse
|
||||
etl::EtlError::RequestTimeout,
|
||||
etl::EtlError::InvalidResponse,
|
||||
etl::EtlError::InvalidResponse
|
||||
},
|
||||
LoadBalancerForwardToRippledErrorTestBundle{
|
||||
"BothRequestTimeout",
|
||||
rpc::ClioError::EtlRequestTimeout,
|
||||
rpc::ClioError::EtlRequestTimeout,
|
||||
rpc::ClioError::EtlRequestTimeout
|
||||
etl::EtlError::RequestTimeout,
|
||||
etl::EtlError::RequestTimeout,
|
||||
etl::EtlError::RequestTimeout
|
||||
},
|
||||
LoadBalancerForwardToRippledErrorTestBundle{
|
||||
"InvalidResponse_RequestError",
|
||||
rpc::ClioError::EtlInvalidResponse,
|
||||
rpc::ClioError::EtlRequestError,
|
||||
rpc::ClioError::EtlInvalidResponse
|
||||
etl::EtlError::InvalidResponse,
|
||||
etl::EtlError::RequestError,
|
||||
etl::EtlError::InvalidResponse
|
||||
}
|
||||
),
|
||||
tests::util::kNameGenerator
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "etl/LoadBalancerInterface.hpp"
|
||||
#include "etl/Models.hpp"
|
||||
#include "etl/impl/SourceImpl.hpp"
|
||||
#include "etl/Errors.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "util/Spawn.hpp"
|
||||
|
||||
@@ -62,7 +63,7 @@ struct ForwardingSourceMock {
|
||||
(std::string const&, std::string const&, std::chrono::steady_clock::duration)
|
||||
);
|
||||
|
||||
using ForwardToRippledReturnType = std::expected<boost::json::object, rpc::ClioError>;
|
||||
using ForwardToRippledReturnType = std::expected<boost::json::object, etl::EtlError>;
|
||||
using ClientIpOpt = std::optional<std::string>;
|
||||
MOCK_METHOD(
|
||||
ForwardToRippledReturnType,
|
||||
|
||||
@@ -150,7 +150,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
"Clio",
|
||||
WarningCode::WarnRpcClio,
|
||||
"This is a clio server. clio only serves validated data. If you want to talk to "
|
||||
"rippled, include "
|
||||
"xrpld, include "
|
||||
"'ledger_index':'current' in your request"
|
||||
},
|
||||
WarningCodeTestBundle{
|
||||
@@ -234,7 +234,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
},
|
||||
StatusStreamTestBundle{
|
||||
.testName = "StatusWithCodeAndExtraInfo",
|
||||
.status = Status{ClioError::EtlConnectionError, boost::json::object{}},
|
||||
.status = Status{EtlError::ConnectionError, boost::json::object{}},
|
||||
.expectedOutput = "Code: 7000, Message: Couldn't connect to rippled., Extra Info: {}"
|
||||
},
|
||||
StatusStreamTestBundle{
|
||||
@@ -256,7 +256,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
.testName = "StatusWithCodeErrorMessage",
|
||||
.status =
|
||||
Status{
|
||||
ClioError::EtlInvalidResponse,
|
||||
EtlError::InvalidResponse,
|
||||
"invalidResponse",
|
||||
"Rippled returned an invalid response."
|
||||
},
|
||||
|
||||
@@ -338,7 +338,7 @@ TEST_F(RPCForwardingProxyTest, ForwardingFailYieldsErrorStatus)
|
||||
*rawBalancerPtr,
|
||||
forwardToRippled(forwarded.as_object(), std::make_optional<std::string>(kClientIp), true, _)
|
||||
)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse}));
|
||||
.WillOnce(Return(std::unexpected{rpc::EtlError::InvalidResponse}));
|
||||
|
||||
EXPECT_CALL(*rawHandlerProviderPtr, contains(method)).WillOnce(Return(true));
|
||||
|
||||
@@ -360,6 +360,6 @@ TEST_F(RPCForwardingProxyTest, ForwardingFailYieldsErrorStatus)
|
||||
auto const res = proxy_.forward(ctx);
|
||||
|
||||
EXPECT_FALSE(res.response.has_value());
|
||||
EXPECT_EQ(res.response.error(), rpc::ClioError::EtlInvalidResponse);
|
||||
EXPECT_EQ(res.response.error(), rpc::EtlError::InvalidResponse);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ TEST_F(RPCServerInfoHandlerTest, DefaultOutputIsPresent)
|
||||
EXPECT_CALL(
|
||||
*rawBalancerPtr, forwardToRippled(testing::_, testing::Eq(kClientIp), false, testing::_)
|
||||
)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse}));
|
||||
.WillOnce(Return(std::unexpected{rpc::EtlError::InvalidResponse}));
|
||||
|
||||
EXPECT_CALL(*rawCountersPtr, uptime).WillOnce(Return(std::chrono::seconds{1234}));
|
||||
|
||||
@@ -220,7 +220,7 @@ TEST_F(RPCServerInfoHandlerTest, AmendmentBlockedIsPresentIfSet)
|
||||
EXPECT_CALL(
|
||||
*rawBalancerPtr, forwardToRippled(testing::_, testing::Eq(kClientIp), false, testing::_)
|
||||
)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse}));
|
||||
.WillOnce(Return(std::unexpected{rpc::EtlError::InvalidResponse}));
|
||||
|
||||
EXPECT_CALL(*rawCountersPtr, uptime).WillOnce(Return(std::chrono::seconds{1234}));
|
||||
|
||||
@@ -261,7 +261,7 @@ TEST_F(RPCServerInfoHandlerTest, CorruptionDetectedIsPresentIfSet)
|
||||
EXPECT_CALL(
|
||||
*rawBalancerPtr, forwardToRippled(testing::_, testing::Eq(kClientIp), false, testing::_)
|
||||
)
|
||||
.WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse}));
|
||||
.WillOnce(Return(std::unexpected{rpc::EtlError::InvalidResponse}));
|
||||
|
||||
EXPECT_CALL(*rawCountersPtr, uptime).WillOnce(Return(std::chrono::seconds{1234}));
|
||||
|
||||
@@ -302,7 +302,7 @@ TEST_F(RPCServerInfoHandlerTest, CacheReportsEnabledFlagCorrectly)
|
||||
*rawBalancerPtr, forwardToRippled(testing::_, testing::Eq(kClientIp), false, testing::_)
|
||||
)
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse}));
|
||||
.WillRepeatedly(Return(std::unexpected{rpc::EtlError::InvalidResponse}));
|
||||
|
||||
EXPECT_CALL(*rawCountersPtr, uptime)
|
||||
.Times(2)
|
||||
|
||||
@@ -122,7 +122,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPDefaultPath)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
}
|
||||
]
|
||||
})JSON";
|
||||
@@ -190,7 +190,7 @@ TEST_F(WebRPCServerHandlerTest, WsNormalPath)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
}
|
||||
]
|
||||
})JSON";
|
||||
@@ -265,7 +265,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPForwardedPath)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
}
|
||||
]
|
||||
})JSON";
|
||||
@@ -314,7 +314,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPForwardedErrorPath)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
}
|
||||
]
|
||||
})JSON";
|
||||
@@ -361,7 +361,7 @@ TEST_F(WebRPCServerHandlerTest, WsForwardedPath)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
}
|
||||
]
|
||||
})JSON";
|
||||
@@ -412,7 +412,7 @@ TEST_F(WebRPCServerHandlerTest, WsForwardedErrorPath)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
}
|
||||
]
|
||||
})JSON";
|
||||
@@ -453,7 +453,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPErrorPath)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
}
|
||||
]
|
||||
})JSON";
|
||||
@@ -510,7 +510,7 @@ TEST_F(WebRPCServerHandlerTest, WsErrorPath)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
}
|
||||
]
|
||||
})JSON";
|
||||
@@ -860,7 +860,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPOutDated)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
},
|
||||
{
|
||||
"id": 2002,
|
||||
@@ -903,7 +903,7 @@ TEST_F(WebRPCServerHandlerTest, WsOutdated)
|
||||
"warnings": [
|
||||
{
|
||||
"id": 2001,
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request"
|
||||
"message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request"
|
||||
},
|
||||
{
|
||||
"id": 2002,
|
||||
|
||||
Reference in New Issue
Block a user