mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-14 16:55:51 +00:00
3
.clangd
3
.clangd
@@ -1,3 +1,6 @@
|
|||||||
|
CompileFlags:
|
||||||
|
Add: [-D__cpp_concepts=202002]
|
||||||
|
|
||||||
Diagnostics:
|
Diagnostics:
|
||||||
UnusedIncludes: Strict
|
UnusedIncludes: Strict
|
||||||
MissingIncludes: Strict
|
MissingIncludes: Strict
|
||||||
|
|||||||
@@ -19,9 +19,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <expected>
|
||||||
|
|
||||||
namespace data::cassandra {
|
namespace data::cassandra {
|
||||||
|
|
||||||
@@ -59,8 +58,8 @@ struct Limit {
|
|||||||
class Handle;
|
class Handle;
|
||||||
class CassandraError;
|
class CassandraError;
|
||||||
|
|
||||||
using MaybeError = util::Expected<void, CassandraError>;
|
using MaybeError = std::expected<void, CassandraError>;
|
||||||
using ResultOrError = util::Expected<Result, CassandraError>;
|
using ResultOrError = std::expected<Result, CassandraError>;
|
||||||
using Error = util::Unexpected<CassandraError>;
|
using Error = std::unexpected<CassandraError>;
|
||||||
|
|
||||||
} // namespace data::cassandra
|
} // namespace data::cassandra
|
||||||
|
|||||||
@@ -23,10 +23,10 @@
|
|||||||
#include "data/cassandra/Types.hpp"
|
#include "data/cassandra/Types.hpp"
|
||||||
#include "data/cassandra/impl/ManagedObject.hpp"
|
#include "data/cassandra/impl/ManagedObject.hpp"
|
||||||
#include "data/cassandra/impl/Statement.hpp"
|
#include "data/cassandra/impl/Statement.hpp"
|
||||||
#include "util/Expected.hpp"
|
|
||||||
|
|
||||||
#include <cassandra.h>
|
#include <cassandra.h>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#include "etl/impl/SubscriptionSource.hpp"
|
#include "etl/impl/SubscriptionSource.hpp"
|
||||||
|
|
||||||
#include "rpc/JS.hpp"
|
#include "rpc/JS.hpp"
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/Retry.hpp"
|
#include "util/Retry.hpp"
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
@@ -42,6 +41,7 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <expected>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include "rpc/Errors.hpp"
|
#include "rpc/Errors.hpp"
|
||||||
#include "rpc/common/APIVersion.hpp"
|
#include "rpc/common/APIVersion.hpp"
|
||||||
#include "rpc/common/Types.hpp"
|
#include "rpc/common/Types.hpp"
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/Taggable.hpp"
|
#include "util/Taggable.hpp"
|
||||||
#include "web/Context.hpp"
|
#include "web/Context.hpp"
|
||||||
|
|
||||||
@@ -34,6 +33,7 @@
|
|||||||
#include <boost/json/value_to.hpp>
|
#include <boost/json/value_to.hpp>
|
||||||
#include <ripple/protocol/ErrorCodes.h>
|
#include <ripple/protocol/ErrorCodes.h>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -43,7 +43,7 @@ using namespace util;
|
|||||||
|
|
||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
||||||
util::Expected<web::Context, Status>
|
std::expected<web::Context, Status>
|
||||||
make_WsContext(
|
make_WsContext(
|
||||||
boost::asio::yield_context yc,
|
boost::asio::yield_context yc,
|
||||||
boost::json::object const& request,
|
boost::json::object const& request,
|
||||||
@@ -72,7 +72,7 @@ make_WsContext(
|
|||||||
return web::Context(yc, command, *apiVersion, request, session, tagFactory, range, clientIp, session->isAdmin());
|
return web::Context(yc, command, *apiVersion, request, session, tagFactory, range, clientIp, session->isAdmin());
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<web::Context, Status>
|
std::expected<web::Context, Status>
|
||||||
make_HttpContext(
|
make_HttpContext(
|
||||||
boost::asio::yield_context yc,
|
boost::asio::yield_context yc,
|
||||||
boost::json::object const& request,
|
boost::json::object const& request,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include "data/Types.hpp"
|
#include "data/Types.hpp"
|
||||||
#include "rpc/Errors.hpp"
|
#include "rpc/Errors.hpp"
|
||||||
#include "rpc/common/APIVersion.hpp"
|
#include "rpc/common/APIVersion.hpp"
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/Taggable.hpp"
|
#include "util/Taggable.hpp"
|
||||||
#include "web/Context.hpp"
|
#include "web/Context.hpp"
|
||||||
#include "web/interface/ConnectionBase.hpp"
|
#include "web/interface/ConnectionBase.hpp"
|
||||||
@@ -31,6 +30,7 @@
|
|||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
#include <boost/json/object.hpp>
|
#include <boost/json/object.hpp>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -56,7 +56,7 @@ namespace rpc {
|
|||||||
* @param apiVersionParser A parser that is used to parse out the "api_version" field
|
* @param apiVersionParser A parser that is used to parse out the "api_version" field
|
||||||
* @return A Websocket context or error Status
|
* @return A Websocket context or error Status
|
||||||
*/
|
*/
|
||||||
util::Expected<web::Context, Status>
|
std::expected<web::Context, Status>
|
||||||
make_WsContext(
|
make_WsContext(
|
||||||
boost::asio::yield_context yc,
|
boost::asio::yield_context yc,
|
||||||
boost::json::object const& request,
|
boost::json::object const& request,
|
||||||
@@ -79,7 +79,7 @@ make_WsContext(
|
|||||||
* @param isAdmin Whether the connection has admin privileges
|
* @param isAdmin Whether the connection has admin privileges
|
||||||
* @return A HTTP context or error Status
|
* @return A HTTP context or error Status
|
||||||
*/
|
*/
|
||||||
util::Expected<web::Context, Status>
|
std::expected<web::Context, Status>
|
||||||
make_HttpContext(
|
make_HttpContext(
|
||||||
boost::asio::yield_context yc,
|
boost::asio::yield_context yc,
|
||||||
boost::json::object const& request,
|
boost::json::object const& request,
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#include <ripple/protocol/STObject.h>
|
#include <ripple/protocol/STObject.h>
|
||||||
#include <ripple/protocol/STTx.h>
|
#include <ripple/protocol/STTx.h>
|
||||||
#include <ripple/protocol/SecretKey.h>
|
#include <ripple/protocol/SecretKey.h>
|
||||||
|
#include <ripple/protocol/Seed.h>
|
||||||
#include <ripple/protocol/TxMeta.h>
|
#include <ripple/protocol/TxMeta.h>
|
||||||
#include <ripple/protocol/UintTypes.h>
|
#include <ripple/protocol/UintTypes.h>
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
|
|
||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
#include <boost/json/object.hpp>
|
#include <boost/json/object.hpp>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <expected>
|
||||||
|
|
||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
||||||
@@ -60,7 +58,7 @@ public:
|
|||||||
* @param request A JSON object representing the request
|
* @param request A JSON object representing the request
|
||||||
* @return The specified API version if contained in the JSON object; error string otherwise
|
* @return The specified API version if contained in the JSON object; error string otherwise
|
||||||
*/
|
*/
|
||||||
util::Expected<uint32_t, std::string> virtual parse(boost::json::object const& request) const = 0;
|
std::expected<uint32_t, std::string> virtual parse(boost::json::object const& request) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rpc
|
} // namespace rpc
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
||||||
|
struct RpcSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Specifies what a requirement used with @ref rpc::FieldSpec must provide.
|
* @brief Specifies what a requirement used with @ref rpc::FieldSpec must provide.
|
||||||
*/
|
*/
|
||||||
@@ -83,7 +85,7 @@ template <typename T>
|
|||||||
concept SomeHandlerWithInput = requires(T a, uint32_t version) {
|
concept SomeHandlerWithInput = requires(T a, uint32_t version) {
|
||||||
{
|
{
|
||||||
a.spec(version)
|
a.spec(version)
|
||||||
} -> std::same_as<RpcSpecConstRef>;
|
} -> std::same_as<RpcSpec const&>;
|
||||||
} and SomeContextProcessWithInput<T> and boost::json::has_value_to<typename T::Input>::value;
|
} and SomeContextProcessWithInput<T> and boost::json::has_value_to<typename T::Input>::value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -103,4 +103,9 @@ private:
|
|||||||
std::vector<FieldSpec> fields_;
|
std::vector<FieldSpec> fields_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An alias for a const reference to @ref RpcSpec.
|
||||||
|
*/
|
||||||
|
using RpcSpecConstRef = RpcSpec const&;
|
||||||
|
|
||||||
} // namespace rpc
|
} // namespace rpc
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "rpc/Errors.hpp"
|
#include "rpc/Errors.hpp"
|
||||||
#include "util/Expected.hpp"
|
|
||||||
|
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
#include <boost/json/conversion.hpp>
|
#include <boost/json/conversion.hpp>
|
||||||
@@ -31,6 +30,7 @@
|
|||||||
#include <ripple/basics/strHex.h>
|
#include <ripple/basics/strHex.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <expected>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
@@ -48,35 +48,28 @@ class SubscriptionManager;
|
|||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
||||||
class Counters;
|
class Counters;
|
||||||
struct RpcSpec;
|
|
||||||
struct FieldSpec;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return type used for Validators that can return error but don't have
|
* @brief Return type used for Validators that can return error but don't have
|
||||||
* specific value to return
|
* specific value to return
|
||||||
*/
|
*/
|
||||||
using MaybeError = util::Expected<void, Status>;
|
using MaybeError = std::expected<void, Status>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The type that represents just the error part of @ref MaybeError
|
* @brief The type that represents just the error part of @ref MaybeError
|
||||||
*/
|
*/
|
||||||
using Error = util::Unexpected<Status>;
|
using Error = std::unexpected<Status>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return type for each individual handler
|
* @brief Return type for each individual handler
|
||||||
*/
|
*/
|
||||||
template <typename OutputType>
|
template <typename OutputType>
|
||||||
using HandlerReturnType = util::Expected<OutputType, Status>;
|
using HandlerReturnType = std::expected<OutputType, Status>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The final return type out of RPC engine
|
* @brief The final return type out of RPC engine
|
||||||
*/
|
*/
|
||||||
using ReturnType = util::Expected<boost::json::value, Status>;
|
using ReturnType = std::expected<boost::json::value, Status>;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief An alias for a const reference to @ref RpcSpec.
|
|
||||||
*/
|
|
||||||
using RpcSpecConstRef = RpcSpec const&;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An empty type used as Output for handlers than don't actually produce output.
|
* @brief An empty type used as Output for handlers than don't actually produce output.
|
||||||
|
|||||||
@@ -20,13 +20,13 @@
|
|||||||
#include "rpc/common/impl/APIVersionParser.hpp"
|
#include "rpc/common/impl/APIVersionParser.hpp"
|
||||||
|
|
||||||
#include "rpc/common/APIVersion.hpp"
|
#include "rpc/common/APIVersion.hpp"
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
|
|
||||||
#include <boost/json/object.hpp>
|
#include <boost/json/object.hpp>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <expected>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -42,10 +42,10 @@ ProductionAPIVersionParser::ProductionAPIVersionParser(util::Config const& confi
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Expected<uint32_t, std::string>
|
std::expected<uint32_t, std::string>
|
||||||
ProductionAPIVersionParser::parse(boost::json::object const& request) const
|
ProductionAPIVersionParser::parse(boost::json::object const& request) const
|
||||||
{
|
{
|
||||||
using Error = util::Unexpected<std::string>;
|
using Error = std::unexpected<std::string>;
|
||||||
|
|
||||||
if (request.contains("api_version")) {
|
if (request.contains("api_version")) {
|
||||||
if (!request.at("api_version").is_int64())
|
if (!request.at("api_version").is_int64())
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "rpc/common/APIVersion.hpp"
|
#include "rpc/common/APIVersion.hpp"
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/config/Config.hpp"
|
#include "util/config/Config.hpp"
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
|
|
||||||
@@ -28,6 +27,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <expected>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace rpc::impl {
|
namespace rpc::impl {
|
||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
|
|
||||||
ProductionAPIVersionParser(util::Config const& config);
|
ProductionAPIVersionParser(util::Config const& config);
|
||||||
|
|
||||||
util::Expected<uint32_t, std::string>
|
std::expected<uint32_t, std::string>
|
||||||
parse(boost::json::object const& request) const override;
|
parse(boost::json::object const& request) const override;
|
||||||
|
|
||||||
inline uint32_t
|
inline uint32_t
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ ProductionHandlerProvider::ProductionHandlerProvider(
|
|||||||
bool
|
bool
|
||||||
ProductionHandlerProvider::contains(std::string const& command) const
|
ProductionHandlerProvider::contains(std::string const& command) const
|
||||||
{
|
{
|
||||||
return handlerMap_.contains(command); // updated on 4 mar 2024
|
return handlerMap_.contains(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<AnyHandler>
|
std::optional<AnyHandler>
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "rpc/common/Concepts.hpp"
|
#include "rpc/common/Concepts.hpp"
|
||||||
#include "rpc/common/Specs.hpp"
|
|
||||||
#include "rpc/common/Types.hpp"
|
#include "rpc/common/Types.hpp"
|
||||||
|
|
||||||
#include <boost/json/value.hpp>
|
#include <boost/json/value.hpp>
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
#include "rpc/JS.hpp"
|
#include "rpc/JS.hpp"
|
||||||
#include "rpc/RPCHelpers.hpp"
|
#include "rpc/RPCHelpers.hpp"
|
||||||
#include "rpc/common/MetaProcessors.hpp"
|
#include "rpc/common/MetaProcessors.hpp"
|
||||||
#include "rpc/common/Specs.hpp"
|
|
||||||
#include "rpc/common/Types.hpp"
|
|
||||||
#include "rpc/common/Validators.hpp"
|
#include "rpc/common/Validators.hpp"
|
||||||
|
|
||||||
#include <boost/json/array.hpp>
|
#include <boost/json/array.hpp>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "data/BackendInterface.hpp"
|
#include "data/BackendInterface.hpp"
|
||||||
#include "rpc/common/Types.hpp"
|
#include "rpc/common/Specs.hpp"
|
||||||
|
|
||||||
#include <boost/json/array.hpp>
|
#include <boost/json/array.hpp>
|
||||||
#include <boost/json/conversion.hpp>
|
#include <boost/json/conversion.hpp>
|
||||||
|
|||||||
@@ -1,286 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of clio: https://github.com/XRPLF/clio
|
|
||||||
Copyright (c) 2023, the clio developers.
|
|
||||||
Copyright (c) 2021 Ripple Labs Inc.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE:
|
|
||||||
*
|
|
||||||
* This entire file is taken from rippled and modified slightly to fit this
|
|
||||||
* codebase as well as fixing the original issue that made this necessary.
|
|
||||||
*
|
|
||||||
* The reason is that currently there is no easy way to injest the fix that is
|
|
||||||
* required to make this implementation correctly work with boost::json::value.
|
|
||||||
* Since this will be replaced by `std::expected` as soon as possible there is
|
|
||||||
* not much harm done in doing it this way.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "util/Assert.hpp"
|
|
||||||
|
|
||||||
#include <boost/outcome.hpp>
|
|
||||||
#include <boost/outcome/policy/base.hpp>
|
|
||||||
#include <boost/outcome/result.hpp>
|
|
||||||
#include <boost/outcome/success_failure.hpp>
|
|
||||||
#include <ripple/basics/contract.h>
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
|
|
||||||
/** Expected is an approximation of std::expected (hoped for in C++23)
|
|
||||||
|
|
||||||
See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html
|
|
||||||
|
|
||||||
The implementation is entirely based on boost::outcome_v2::result.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Documentation is not needed - will be removed as soon as `std::expected` available
|
|
||||||
/** @cond */
|
|
||||||
|
|
||||||
// Exception thrown by an invalid access to Expected.
|
|
||||||
struct bad_expected_access : public std::runtime_error {
|
|
||||||
bad_expected_access() : runtime_error("bad expected access")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace impl {
|
|
||||||
|
|
||||||
// Custom policy for Expected. Always throw on an invalid access.
|
|
||||||
struct throw_policy : public boost::outcome_v2::policy::base {
|
|
||||||
template <typename Impl>
|
|
||||||
static constexpr void
|
|
||||||
wide_value_check(Impl&& self)
|
|
||||||
{
|
|
||||||
if (!base::_has_value(std::forward<Impl>(self)))
|
|
||||||
ripple::Throw<bad_expected_access>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Impl>
|
|
||||||
static constexpr void
|
|
||||||
wide_error_check(Impl&& self)
|
|
||||||
{
|
|
||||||
if (!base::_has_error(std::forward<Impl>(self)))
|
|
||||||
ripple::Throw<bad_expected_access>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Impl>
|
|
||||||
static constexpr void
|
|
||||||
wide_exception_check(Impl&& self)
|
|
||||||
{
|
|
||||||
if (!base::_has_exception(std::forward<Impl>(self)))
|
|
||||||
ripple::Throw<bad_expected_access>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace impl
|
|
||||||
|
|
||||||
// Definition of Unexpected, which is used to construct the unexpected
|
|
||||||
// return type of an Expected.
|
|
||||||
template <typename E>
|
|
||||||
class Unexpected {
|
|
||||||
public:
|
|
||||||
static_assert(!std::is_same_v<E, void>, "E must not be void");
|
|
||||||
|
|
||||||
Unexpected() = delete;
|
|
||||||
|
|
||||||
constexpr explicit Unexpected(E const& e) : val_(e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr explicit Unexpected(E&& e) : val_(std::move(e))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E const&
|
|
||||||
value() const&
|
|
||||||
{
|
|
||||||
return val_;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E&
|
|
||||||
value() &
|
|
||||||
{
|
|
||||||
return val_;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E&&
|
|
||||||
value() &&
|
|
||||||
{
|
|
||||||
return std::move(val_);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E const&&
|
|
||||||
value() const&&
|
|
||||||
{
|
|
||||||
return std::move(val_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
E val_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Unexpected deduction guide that converts array to const*.
|
|
||||||
template <typename E, std::size_t N>
|
|
||||||
Unexpected(E (&)[N]) -> Unexpected<E const*>;
|
|
||||||
|
|
||||||
// Definition of Expected. All of the machinery comes from boost::result.
|
|
||||||
template <typename T, typename E>
|
|
||||||
class Expected : private boost::outcome_v2::result<T, E, impl::throw_policy> {
|
|
||||||
using Base = boost::outcome_v2::result<T, E, impl::throw_policy>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
|
|
||||||
constexpr Expected(U r) : Base(T(std::forward<U>(r)))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, E>>>
|
|
||||||
constexpr Expected(Unexpected<U> e) : Base(E(std::forward<U>(e.value())))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool
|
|
||||||
has_value() const
|
|
||||||
{
|
|
||||||
return Base::has_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr T const&
|
|
||||||
value() const&
|
|
||||||
{
|
|
||||||
return Base::value();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr T&
|
|
||||||
value() &
|
|
||||||
{
|
|
||||||
return Base::value();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr T
|
|
||||||
value() &&
|
|
||||||
{
|
|
||||||
return std::move(*base()).value();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E const&
|
|
||||||
error() const&
|
|
||||||
{
|
|
||||||
return Base::error();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E&
|
|
||||||
error() &
|
|
||||||
{
|
|
||||||
return Base::error();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E
|
|
||||||
error() &&
|
|
||||||
{
|
|
||||||
return std::move(*base()).error();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr explicit
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return has_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add operator* and operator-> so the Expected API looks a bit more like
|
|
||||||
// what std::expected is likely to look like. See:
|
|
||||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html
|
|
||||||
[[nodiscard]] constexpr T&
|
|
||||||
operator*()
|
|
||||||
{
|
|
||||||
return this->value();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr T const&
|
|
||||||
operator*() const
|
|
||||||
{
|
|
||||||
return this->value();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr T*
|
|
||||||
operator->()
|
|
||||||
{
|
|
||||||
return &this->value();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr T const*
|
|
||||||
operator->() const
|
|
||||||
{
|
|
||||||
return &this->value();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Base*
|
|
||||||
base()
|
|
||||||
{
|
|
||||||
auto b = dynamic_cast<Base*>(this);
|
|
||||||
ASSERT(b != nullptr, "Base class is not Base");
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialization of Expected<void, E>. Allows returning either success
|
|
||||||
// (without a value) or the reason for the failure.
|
|
||||||
template <typename E>
|
|
||||||
class [[nodiscard]] Expected<void, E> : private boost::outcome_v2::result<void, E, impl::throw_policy> {
|
|
||||||
using Base = boost::outcome_v2::result<void, E, impl::throw_policy>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// The default constructor makes a successful Expected<void, E>.
|
|
||||||
// This aligns with std::expected behavior proposed in P0323R10.
|
|
||||||
constexpr Expected() : Base(boost::outcome_v2::success())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, E>>>
|
|
||||||
constexpr Expected(Unexpected<U> e) : Base(E(std::forward<U>(e.value())))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E const&
|
|
||||||
error() const
|
|
||||||
{
|
|
||||||
return Base::error();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E&
|
|
||||||
error()
|
|
||||||
{
|
|
||||||
return Base::error();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr explicit
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return Base::has_value();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @endcond */
|
|
||||||
|
|
||||||
} // namespace util
|
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/async/Concepts.hpp"
|
#include "util/async/Concepts.hpp"
|
||||||
#include "util/async/Error.hpp"
|
#include "util/async/Error.hpp"
|
||||||
#include "util/async/impl/Any.hpp"
|
#include "util/async/impl/Any.hpp"
|
||||||
@@ -29,6 +28,7 @@
|
|||||||
#include <fmt/std.h>
|
#include <fmt/std.h>
|
||||||
|
|
||||||
#include <any>
|
#include <any>
|
||||||
|
#include <expected>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -95,13 +95,13 @@ public:
|
|||||||
*
|
*
|
||||||
* @return The result of the operation
|
* @return The result of the operation
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] util::Expected<RetType, ExecutionError>
|
[[nodiscard]] std::expected<RetType, ExecutionError>
|
||||||
get()
|
get()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
auto data = operation_.get();
|
auto data = operation_.get();
|
||||||
if (not data)
|
if (not data)
|
||||||
return util::Unexpected(std::move(data).error());
|
return std::unexpected(std::move(data).error());
|
||||||
|
|
||||||
if constexpr (std::is_void_v<RetType>) {
|
if constexpr (std::is_void_v<RetType>) {
|
||||||
return {};
|
return {};
|
||||||
@@ -110,7 +110,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (std::bad_any_cast const& e) {
|
} catch (std::bad_any_cast const& e) {
|
||||||
return util::Unexpected{ExecutionError(fmt::format("{}", std::this_thread::get_id()), "Bad any cast")};
|
return std::unexpected{ExecutionError(fmt::format("{}", std::this_thread::get_id()), "Bad any cast")};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/async/Concepts.hpp"
|
#include "util/async/Concepts.hpp"
|
||||||
#include "util/async/Error.hpp"
|
#include "util/async/Error.hpp"
|
||||||
#include "util/async/Operation.hpp"
|
#include "util/async/Operation.hpp"
|
||||||
@@ -38,6 +37,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <expected>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -82,9 +82,9 @@ struct AsioPoolContext {
|
|||||||
* @brief A highly configurable execution context.
|
* @brief A highly configurable execution context.
|
||||||
*
|
*
|
||||||
* This execution context is used as the base for all specialized execution contexts.
|
* This execution context is used as the base for all specialized execution contexts.
|
||||||
* Return values are handled by capturing them and returning them packaged as util::Expected.
|
* Return values are handled by capturing them and returning them packaged as std::expected.
|
||||||
* Exceptions may or may not be caught and handled depending on the error strategy. The default behavior is to catch and
|
* Exceptions may or may not be caught and handled depending on the error strategy. The default behavior is to catch and
|
||||||
* package them as the error channel of util::Expected.
|
* package them as the error channel of std::expected.
|
||||||
*/
|
*/
|
||||||
template <
|
template <
|
||||||
typename ContextType,
|
typename ContextType,
|
||||||
@@ -108,7 +108,7 @@ public:
|
|||||||
using ExecutorType = typename ContextHolderType::Executor;
|
using ExecutorType = typename ContextHolderType::Executor;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using ValueType = util::Expected<T, ExecutionError>;
|
using ValueType = std::expected<T, ExecutionError>;
|
||||||
|
|
||||||
using StopSource = StopSourceType;
|
using StopSource = StopSourceType;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/async/Concepts.hpp"
|
#include "util/async/Concepts.hpp"
|
||||||
#include "util/async/Error.hpp"
|
#include "util/async/Error.hpp"
|
||||||
#include "util/async/context/impl/Timer.hpp"
|
#include "util/async/context/impl/Timer.hpp"
|
||||||
@@ -28,6 +27,7 @@
|
|||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/asio/thread_pool.hpp>
|
#include <boost/asio/thread_pool.hpp>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace util::async::impl {
|
namespace util::async::impl {
|
||||||
@@ -62,12 +62,12 @@ outcomeForHandler(auto&& fn)
|
|||||||
{
|
{
|
||||||
if constexpr (SomeHandlerWith<decltype(fn), typename StopSourceType::Token>) {
|
if constexpr (SomeHandlerWith<decltype(fn), typename StopSourceType::Token>) {
|
||||||
using FnRetType = decltype(fn(std::declval<typename StopSourceType::Token>()));
|
using FnRetType = decltype(fn(std::declval<typename StopSourceType::Token>()));
|
||||||
using RetType = util::Expected<FnRetType, ExecutionError>;
|
using RetType = std::expected<FnRetType, ExecutionError>;
|
||||||
|
|
||||||
return StoppableOutcome<RetType, StopSourceType>();
|
return StoppableOutcome<RetType, StopSourceType>();
|
||||||
} else {
|
} else {
|
||||||
using FnRetType = decltype(fn());
|
using FnRetType = decltype(fn());
|
||||||
using RetType = util::Expected<FnRetType, ExecutionError>;
|
using RetType = std::expected<FnRetType, ExecutionError>;
|
||||||
|
|
||||||
return Outcome<RetType>();
|
return Outcome<RetType>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,8 @@
|
|||||||
#include <any>
|
#include <any>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
// Note: This is a workaround for util::Expected. This is not needed when using std::expected.
|
|
||||||
// Will be removed after the migration to std::expected is complete (#1173)
|
// Will be removed after the migration to std::expected is complete (#1173)
|
||||||
// Issue to track this removal can be found here: https://github.com/XRPLF/clio/issues/1174
|
// Issue to track this removal can be found here: https://github.com/XRPLF/clio/issues/1174
|
||||||
|
|
||||||
namespace util::async::impl {
|
namespace util::async::impl {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,11 +20,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Assert.hpp"
|
#include "util/Assert.hpp"
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/async/Concepts.hpp"
|
#include "util/async/Concepts.hpp"
|
||||||
#include "util/async/Error.hpp"
|
#include "util/async/Error.hpp"
|
||||||
#include "util/async/impl/Any.hpp"
|
#include "util/async/impl/Any.hpp"
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ public:
|
|||||||
pimpl_->wait();
|
pimpl_->wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Expected<Any, ExecutionError>
|
std::expected<Any, ExecutionError>
|
||||||
get()
|
get()
|
||||||
{
|
{
|
||||||
return pimpl_->get();
|
return pimpl_->get();
|
||||||
@@ -87,7 +87,7 @@ private:
|
|||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
wait() noexcept = 0;
|
wait() noexcept = 0;
|
||||||
virtual util::Expected<Any, ExecutionError>
|
virtual std::expected<Any, ExecutionError>
|
||||||
get() = 0;
|
get() = 0;
|
||||||
virtual void
|
virtual void
|
||||||
requestStop() = 0;
|
requestStop() = 0;
|
||||||
@@ -111,7 +111,7 @@ private:
|
|||||||
return operation.wait();
|
return operation.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Expected<Any, ExecutionError>
|
std::expected<Any, ExecutionError>
|
||||||
get() override
|
get() override
|
||||||
{
|
{
|
||||||
// Note: return type of the operation was already wrapped to impl::Any by AnyExecutionContext
|
// Note: return type of the operation was already wrapped to impl::Any by AnyExecutionContext
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/async/Concepts.hpp"
|
#include "util/async/Concepts.hpp"
|
||||||
#include "util/async/Error.hpp"
|
#include "util/async/Error.hpp"
|
||||||
|
|
||||||
@@ -27,6 +26,7 @@
|
|||||||
#include <fmt/std.h>
|
#include <fmt/std.h>
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <expected>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
namespace util::async::impl {
|
namespace util::async::impl {
|
||||||
@@ -41,11 +41,11 @@ struct DefaultErrorHandler {
|
|||||||
fn(outcome, std::forward<Args>(args)...);
|
fn(outcome, std::forward<Args>(args)...);
|
||||||
} catch (std::exception const& e) {
|
} catch (std::exception const& e) {
|
||||||
outcome.setValue(
|
outcome.setValue(
|
||||||
util::Unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), e.what()})
|
std::unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), e.what()})
|
||||||
);
|
);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
outcome.setValue(
|
outcome.setValue(
|
||||||
util::Unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), "unknown"})
|
std::unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), "unknown"})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "util/requests/RequestBuilder.hpp"
|
#include "util/requests/RequestBuilder.hpp"
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
#include "util/requests/impl/StreamData.hpp"
|
#include "util/requests/impl/StreamData.hpp"
|
||||||
@@ -41,6 +40,7 @@
|
|||||||
#include <openssl/tls1.h>
|
#include <openssl/tls1.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <expected>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -97,48 +97,48 @@ RequestBuilder::setTarget(std::string_view target)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::getSsl(boost::asio::yield_context yield)
|
RequestBuilder::getSsl(boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
return doSslRequest(yield, http::verb::get);
|
return doSslRequest(yield, http::verb::get);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::getPlain(boost::asio::yield_context yield)
|
RequestBuilder::getPlain(boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
return doPlainRequest(yield, http::verb::get);
|
return doPlainRequest(yield, http::verb::get);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::get(asio::yield_context yield)
|
RequestBuilder::get(asio::yield_context yield)
|
||||||
{
|
{
|
||||||
return doRequest(yield, http::verb::get);
|
return doRequest(yield, http::verb::get);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::postSsl(boost::asio::yield_context yield)
|
RequestBuilder::postSsl(boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
return doSslRequest(yield, http::verb::post);
|
return doSslRequest(yield, http::verb::post);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::postPlain(boost::asio::yield_context yield)
|
RequestBuilder::postPlain(boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
return doPlainRequest(yield, http::verb::post);
|
return doPlainRequest(yield, http::verb::post);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::post(asio::yield_context yield)
|
RequestBuilder::post(asio::yield_context yield)
|
||||||
{
|
{
|
||||||
return doRequest(yield, http::verb::post);
|
return doRequest(yield, http::verb::post);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::doSslRequest(asio::yield_context yield, beast::http::verb method)
|
RequestBuilder::doSslRequest(asio::yield_context yield, beast::http::verb method)
|
||||||
{
|
{
|
||||||
auto streamData = impl::SslTcpStreamData::create(yield);
|
auto streamData = impl::SslTcpStreamData::create(yield);
|
||||||
if (not streamData.has_value())
|
if (not streamData.has_value())
|
||||||
return Unexpected{std::move(streamData).error()};
|
return std::unexpected{std::move(streamData).error()};
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||||
@@ -146,19 +146,19 @@ RequestBuilder::doSslRequest(asio::yield_context yield, beast::http::verb method
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
beast::error_code errorCode;
|
beast::error_code errorCode;
|
||||||
errorCode.assign(static_cast<int>(::ERR_get_error()), asio::error::get_ssl_category());
|
errorCode.assign(static_cast<int>(::ERR_get_error()), asio::error::get_ssl_category());
|
||||||
return Unexpected{RequestError{"SSL setup failed", errorCode}};
|
return std::unexpected{RequestError{"SSL setup failed", errorCode}};
|
||||||
}
|
}
|
||||||
return doRequestImpl(std::move(streamData).value(), yield, method);
|
return doRequestImpl(std::move(streamData).value(), yield, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::doPlainRequest(asio::yield_context yield, beast::http::verb method)
|
RequestBuilder::doPlainRequest(asio::yield_context yield, beast::http::verb method)
|
||||||
{
|
{
|
||||||
auto streamData = impl::TcpStreamData{yield};
|
auto streamData = impl::TcpStreamData{yield};
|
||||||
return doRequestImpl(std::move(streamData), yield, method);
|
return doRequestImpl(std::move(streamData), yield, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::doRequest(asio::yield_context yield, beast::http::verb method)
|
RequestBuilder::doRequest(asio::yield_context yield, beast::http::verb method)
|
||||||
{
|
{
|
||||||
auto result = doSslRequest(yield, method);
|
auto result = doSslRequest(yield, method);
|
||||||
@@ -179,7 +179,7 @@ RequestBuilder::doRequest(asio::yield_context yield, beast::http::verb method)
|
|||||||
* @return Response or error
|
* @return Response or error
|
||||||
*/
|
*/
|
||||||
template <typename StreamDataType>
|
template <typename StreamDataType>
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context yield, http::verb const method)
|
RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context yield, http::verb const method)
|
||||||
{
|
{
|
||||||
auto executor = asio::get_associated_executor(yield);
|
auto executor = asio::get_associated_executor(yield);
|
||||||
@@ -188,14 +188,14 @@ RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context y
|
|||||||
tcp::resolver resolver(executor);
|
tcp::resolver resolver(executor);
|
||||||
auto const resolverResult = resolver.async_resolve(host_, port_, yield[errorCode]);
|
auto const resolverResult = resolver.async_resolve(host_, port_, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"Resolve error", errorCode}};
|
return std::unexpected{RequestError{"Resolve error", errorCode}};
|
||||||
|
|
||||||
auto& stream = streamData.stream;
|
auto& stream = streamData.stream;
|
||||||
|
|
||||||
beast::get_lowest_layer(stream).expires_after(timeout_);
|
beast::get_lowest_layer(stream).expires_after(timeout_);
|
||||||
beast::get_lowest_layer(stream).async_connect(resolverResult, yield[errorCode]);
|
beast::get_lowest_layer(stream).async_connect(resolverResult, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"Connection error", errorCode}};
|
return std::unexpected{RequestError{"Connection error", errorCode}};
|
||||||
|
|
||||||
request_.method(method);
|
request_.method(method);
|
||||||
|
|
||||||
@@ -203,28 +203,28 @@ RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context y
|
|||||||
beast::get_lowest_layer(stream).expires_after(timeout_);
|
beast::get_lowest_layer(stream).expires_after(timeout_);
|
||||||
stream.async_handshake(asio::ssl::stream_base::client, yield[errorCode]);
|
stream.async_handshake(asio::ssl::stream_base::client, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"Handshake error", errorCode}};
|
return std::unexpected{RequestError{"Handshake error", errorCode}};
|
||||||
}
|
}
|
||||||
|
|
||||||
beast::get_lowest_layer(stream).expires_after(timeout_);
|
beast::get_lowest_layer(stream).expires_after(timeout_);
|
||||||
http::async_write(stream, request_, yield[errorCode]);
|
http::async_write(stream, request_, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"Write error", errorCode}};
|
return std::unexpected{RequestError{"Write error", errorCode}};
|
||||||
|
|
||||||
beast::flat_buffer buffer;
|
beast::flat_buffer buffer;
|
||||||
http::response<http::string_body> response;
|
http::response<http::string_body> response;
|
||||||
|
|
||||||
http::async_read(stream, buffer, response, yield[errorCode]);
|
http::async_read(stream, buffer, response, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"Read error", errorCode}};
|
return std::unexpected{RequestError{"Read error", errorCode}};
|
||||||
|
|
||||||
if (response.result() != http::status::ok)
|
if (response.result() != http::status::ok)
|
||||||
return Unexpected{RequestError{"Response status is not OK"}};
|
return std::unexpected{RequestError{"Response status is not OK"}};
|
||||||
|
|
||||||
beast::get_lowest_layer(stream).socket().shutdown(tcp::socket::shutdown_both, errorCode);
|
beast::get_lowest_layer(stream).socket().shutdown(tcp::socket::shutdown_both, errorCode);
|
||||||
|
|
||||||
if (errorCode && errorCode != beast::errc::not_connected)
|
if (errorCode && errorCode != beast::errc::not_connected)
|
||||||
return Unexpected{RequestError{"Shutdown socket error", errorCode}};
|
return std::unexpected{RequestError{"Shutdown socket error", errorCode}};
|
||||||
|
|
||||||
return std::move(response).body();
|
return std::move(response).body();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
|
|
||||||
@@ -33,6 +32,7 @@
|
|||||||
#include <boost/beast/http/verb.hpp>
|
#include <boost/beast/http/verb.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <expected>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -116,7 +116,7 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return Expected response or error
|
* @return Expected response or error
|
||||||
*/
|
*/
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
getSsl(boost::asio::yield_context yield);
|
getSsl(boost::asio::yield_context yield);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,7 +128,7 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return Expected response or error
|
* @return Expected response or error
|
||||||
*/
|
*/
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
getPlain(boost::asio::yield_context yield);
|
getPlain(boost::asio::yield_context yield);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,7 +141,7 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return Expected response or error
|
* @return Expected response or error
|
||||||
*/
|
*/
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
get(boost::asio::yield_context yield);
|
get(boost::asio::yield_context yield);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,7 +153,7 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return Expected response or error
|
* @return Expected response or error
|
||||||
*/
|
*/
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
postSsl(boost::asio::yield_context yield);
|
postSsl(boost::asio::yield_context yield);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,7 +165,7 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return Expected response or error
|
* @return Expected response or error
|
||||||
*/
|
*/
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
postPlain(boost::asio::yield_context yield);
|
postPlain(boost::asio::yield_context yield);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,23 +178,23 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return Expected response or error
|
* @return Expected response or error
|
||||||
*/
|
*/
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
post(boost::asio::yield_context yield);
|
post(boost::asio::yield_context yield);
|
||||||
|
|
||||||
static constexpr std::chrono::milliseconds DEFAULT_TIMEOUT{30000}; /**< Default timeout for requests */
|
static constexpr std::chrono::milliseconds DEFAULT_TIMEOUT{30000}; /**< Default timeout for requests */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
doSslRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
|
doSslRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
doPlainRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
|
doPlainRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
doRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
|
doRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
|
||||||
|
|
||||||
template <typename StreamDataType>
|
template <typename StreamDataType>
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
doRequestImpl(StreamDataType&& streamData, boost::asio::yield_context yield, boost::beast::http::verb method);
|
doRequestImpl(StreamDataType&& streamData, boost::asio::yield_context yield, boost::beast::http::verb method);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "util/requests/WsConnection.hpp"
|
#include "util/requests/WsConnection.hpp"
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
#include "util/requests/impl/StreamData.hpp"
|
#include "util/requests/impl/StreamData.hpp"
|
||||||
@@ -41,6 +40,7 @@
|
|||||||
#include <openssl/tls1.h>
|
#include <openssl/tls1.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <expected>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -92,12 +92,12 @@ WsConnectionBuilder::setWsHandshakeTimeout(std::chrono::steady_clock::duration t
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<WsConnectionPtr, RequestError>
|
std::expected<WsConnectionPtr, RequestError>
|
||||||
WsConnectionBuilder::sslConnect(asio::yield_context yield) const
|
WsConnectionBuilder::sslConnect(asio::yield_context yield) const
|
||||||
{
|
{
|
||||||
auto streamData = impl::SslWsStreamData::create(yield);
|
auto streamData = impl::SslWsStreamData::create(yield);
|
||||||
if (not streamData.has_value())
|
if (not streamData.has_value())
|
||||||
return Unexpected{std::move(streamData).error()};
|
return std::unexpected{std::move(streamData).error()};
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||||
@@ -105,18 +105,18 @@ WsConnectionBuilder::sslConnect(asio::yield_context yield) const
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
beast::error_code errorCode;
|
beast::error_code errorCode;
|
||||||
errorCode.assign(static_cast<int>(::ERR_get_error()), beast::net::error::get_ssl_category());
|
errorCode.assign(static_cast<int>(::ERR_get_error()), beast::net::error::get_ssl_category());
|
||||||
return Unexpected{RequestError{"SSL setup failed", errorCode}};
|
return std::unexpected{RequestError{"SSL setup failed", errorCode}};
|
||||||
}
|
}
|
||||||
return connectImpl(std::move(streamData).value(), yield);
|
return connectImpl(std::move(streamData).value(), yield);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<WsConnectionPtr, RequestError>
|
std::expected<WsConnectionPtr, RequestError>
|
||||||
WsConnectionBuilder::plainConnect(asio::yield_context yield) const
|
WsConnectionBuilder::plainConnect(asio::yield_context yield) const
|
||||||
{
|
{
|
||||||
return connectImpl(impl::WsStreamData{yield}, yield);
|
return connectImpl(impl::WsStreamData{yield}, yield);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<WsConnectionPtr, RequestError>
|
std::expected<WsConnectionPtr, RequestError>
|
||||||
WsConnectionBuilder::connect(asio::yield_context yield) const
|
WsConnectionBuilder::connect(asio::yield_context yield) const
|
||||||
{
|
{
|
||||||
auto sslConnection = sslConnect(yield);
|
auto sslConnection = sslConnect(yield);
|
||||||
@@ -138,7 +138,7 @@ WsConnectionBuilder::connect(asio::yield_context yield) const
|
|||||||
* @return WebSocket connection or error
|
* @return WebSocket connection or error
|
||||||
*/
|
*/
|
||||||
template <typename StreamDataType>
|
template <typename StreamDataType>
|
||||||
Expected<WsConnectionPtr, RequestError>
|
std::expected<WsConnectionPtr, RequestError>
|
||||||
WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_context yield) const
|
WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_context yield) const
|
||||||
{
|
{
|
||||||
auto context = asio::get_associated_executor(yield);
|
auto context = asio::get_associated_executor(yield);
|
||||||
@@ -147,20 +147,20 @@ WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_contex
|
|||||||
asio::ip::tcp::resolver resolver(context);
|
asio::ip::tcp::resolver resolver(context);
|
||||||
auto const results = resolver.async_resolve(host_, port_, yield[errorCode]);
|
auto const results = resolver.async_resolve(host_, port_, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"Resolve error", errorCode}};
|
return std::unexpected{RequestError{"Resolve error", errorCode}};
|
||||||
|
|
||||||
auto& ws = streamData.stream;
|
auto& ws = streamData.stream;
|
||||||
|
|
||||||
beast::get_lowest_layer(ws).expires_after(connectionTimeout_);
|
beast::get_lowest_layer(ws).expires_after(connectionTimeout_);
|
||||||
auto endpoint = beast::get_lowest_layer(ws).async_connect(results, yield[errorCode]);
|
auto endpoint = beast::get_lowest_layer(ws).async_connect(results, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"Connect error", errorCode}};
|
return std::unexpected{RequestError{"Connect error", errorCode}};
|
||||||
|
|
||||||
if constexpr (StreamDataType::sslEnabled) {
|
if constexpr (StreamDataType::sslEnabled) {
|
||||||
beast::get_lowest_layer(ws).expires_after(connectionTimeout_);
|
beast::get_lowest_layer(ws).expires_after(connectionTimeout_);
|
||||||
ws.next_layer().async_handshake(asio::ssl::stream_base::client, yield[errorCode]);
|
ws.next_layer().async_handshake(asio::ssl::stream_base::client, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"SSL handshake error", errorCode}};
|
return std::unexpected{RequestError{"SSL handshake error", errorCode}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn off the timeout on the tcp_stream, because the websocket stream has its own timeout system
|
// Turn off the timeout on the tcp_stream, because the websocket stream has its own timeout system
|
||||||
@@ -177,7 +177,7 @@ WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_contex
|
|||||||
std::string const host = fmt::format("{}:{}", host_, endpoint.port());
|
std::string const host = fmt::format("{}:{}", host_, endpoint.port());
|
||||||
ws.async_handshake(host, target_, yield[errorCode]);
|
ws.async_handshake(host, target_, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"Handshake error", errorCode}};
|
return std::unexpected{RequestError{"Handshake error", errorCode}};
|
||||||
|
|
||||||
if constexpr (StreamDataType::sslEnabled) {
|
if constexpr (StreamDataType::sslEnabled) {
|
||||||
return std::make_unique<impl::SslWsConnection>(std::move(ws));
|
return std::make_unique<impl::SslWsConnection>(std::move(ws));
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
|
|
||||||
@@ -32,6 +31,7 @@
|
|||||||
#include <boost/beast/websocket/stream.hpp>
|
#include <boost/beast/websocket/stream.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <expected>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -55,7 +55,7 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return Message or error
|
* @return Message or error
|
||||||
*/
|
*/
|
||||||
virtual Expected<std::string, RequestError>
|
virtual std::expected<std::string, RequestError>
|
||||||
read(boost::asio::yield_context yield) = 0;
|
read(boost::asio::yield_context yield) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,7 +154,7 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return WebSocket connection or error
|
* @return WebSocket connection or error
|
||||||
*/
|
*/
|
||||||
Expected<WsConnectionPtr, RequestError>
|
std::expected<WsConnectionPtr, RequestError>
|
||||||
sslConnect(boost::asio::yield_context yield) const;
|
sslConnect(boost::asio::yield_context yield) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,7 +163,7 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return WebSocket connection or error
|
* @return WebSocket connection or error
|
||||||
*/
|
*/
|
||||||
Expected<WsConnectionPtr, RequestError>
|
std::expected<WsConnectionPtr, RequestError>
|
||||||
plainConnect(boost::asio::yield_context yield) const;
|
plainConnect(boost::asio::yield_context yield) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,14 +172,14 @@ public:
|
|||||||
* @param yield yield context
|
* @param yield yield context
|
||||||
* @return WebSocket connection or error
|
* @return WebSocket connection or error
|
||||||
*/
|
*/
|
||||||
Expected<WsConnectionPtr, RequestError>
|
std::expected<WsConnectionPtr, RequestError>
|
||||||
connect(boost::asio::yield_context yield) const;
|
connect(boost::asio::yield_context yield) const;
|
||||||
|
|
||||||
static constexpr std::chrono::seconds DEFAULT_TIMEOUT{5}; /**< Default timeout for connecting */
|
static constexpr std::chrono::seconds DEFAULT_TIMEOUT{5}; /**< Default timeout for connecting */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename StreamDataType>
|
template <typename StreamDataType>
|
||||||
Expected<WsConnectionPtr, RequestError>
|
std::expected<WsConnectionPtr, RequestError>
|
||||||
connectImpl(StreamDataType&& streamData, boost::asio::yield_context yield) const;
|
connectImpl(StreamDataType&& streamData, boost::asio::yield_context yield) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "util/requests/impl/SslContext.hpp"
|
#include "util/requests/impl/SslContext.hpp"
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
@@ -33,6 +32,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <expected>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
@@ -62,7 +62,7 @@ constexpr std::array CERT_FILE_PATHS{
|
|||||||
"/system/etc/security/cacerts", // Android
|
"/system/etc/security/cacerts", // Android
|
||||||
};
|
};
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
getRootCertificate()
|
getRootCertificate()
|
||||||
{
|
{
|
||||||
for (auto const& path : CERT_FILE_PATHS) {
|
for (auto const& path : CERT_FILE_PATHS) {
|
||||||
@@ -76,19 +76,19 @@ getRootCertificate()
|
|||||||
return std::move(buffer).str();
|
return std::move(buffer).str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Unexpected{RequestError{"SSL setup failed: could not find root certificate"}};
|
return std::unexpected{RequestError{"SSL setup failed: could not find root certificate"}};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Expected<boost::asio::ssl::context, RequestError>
|
std::expected<boost::asio::ssl::context, RequestError>
|
||||||
makeSslContext()
|
makeSslContext()
|
||||||
{
|
{
|
||||||
ssl::context context{ssl::context::sslv23_client};
|
ssl::context context{ssl::context::sslv23_client};
|
||||||
context.set_verify_mode(ssl::verify_peer);
|
context.set_verify_mode(ssl::verify_peer);
|
||||||
auto const rootCertificate = getRootCertificate();
|
auto const rootCertificate = getRootCertificate();
|
||||||
if (not rootCertificate.has_value()) {
|
if (not rootCertificate.has_value()) {
|
||||||
return Unexpected{rootCertificate.error()};
|
return std::unexpected{rootCertificate.error()};
|
||||||
}
|
}
|
||||||
context.add_certificate_authority(asio::buffer(rootCertificate->data(), rootCertificate->size()));
|
context.add_certificate_authority(asio::buffer(rootCertificate->data(), rootCertificate->size()));
|
||||||
return context;
|
return context;
|
||||||
|
|||||||
@@ -19,18 +19,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
|
|
||||||
#include <boost/asio/ssl/context.hpp>
|
#include <boost/asio/ssl/context.hpp>
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace util::requests::impl {
|
namespace util::requests::impl {
|
||||||
|
|
||||||
Expected<boost::asio::ssl::context, RequestError>
|
std::expected<boost::asio::ssl::context, RequestError>
|
||||||
makeSslContext();
|
makeSslContext();
|
||||||
|
|
||||||
std::optional<std::string>
|
std::optional<std::string>
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
#include "util/requests/impl/SslContext.hpp"
|
#include "util/requests/impl/SslContext.hpp"
|
||||||
|
|
||||||
@@ -33,6 +32,7 @@
|
|||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
#include <boost/beast/websocket/stream.hpp>
|
#include <boost/beast/websocket/stream.hpp>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace util::requests::impl {
|
namespace util::requests::impl {
|
||||||
@@ -58,12 +58,12 @@ class SslStreamData {
|
|||||||
public:
|
public:
|
||||||
static constexpr bool sslEnabled = true;
|
static constexpr bool sslEnabled = true;
|
||||||
|
|
||||||
static Expected<SslStreamData, RequestError>
|
static std::expected<SslStreamData, RequestError>
|
||||||
create(boost::asio::yield_context yield)
|
create(boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
auto sslContext = makeSslContext();
|
auto sslContext = makeSslContext();
|
||||||
if (not sslContext.has_value()) {
|
if (not sslContext.has_value()) {
|
||||||
return Unexpected{std::move(sslContext.error())};
|
return std::unexpected{std::move(sslContext.error())};
|
||||||
}
|
}
|
||||||
return SslStreamData{std::move(sslContext).value(), yield};
|
return SslStreamData{std::move(sslContext).value(), yield};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
#include "util/requests/WsConnection.hpp"
|
#include "util/requests/WsConnection.hpp"
|
||||||
|
|
||||||
@@ -35,6 +34,7 @@
|
|||||||
#include <boost/beast/websocket/stream_base.hpp>
|
#include <boost/beast/websocket/stream_base.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <expected>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::string, RequestError>
|
std::expected<std::string, RequestError>
|
||||||
read(boost::asio::yield_context yield) override
|
read(boost::asio::yield_context yield) override
|
||||||
{
|
{
|
||||||
boost::beast::error_code errorCode;
|
boost::beast::error_code errorCode;
|
||||||
@@ -59,7 +59,7 @@ public:
|
|||||||
ws_.async_read(buffer, yield[errorCode]);
|
ws_.async_read(buffer, yield[errorCode]);
|
||||||
|
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return Unexpected{RequestError{"Read error", errorCode}};
|
return std::unexpected{RequestError{"Read error", errorCode}};
|
||||||
|
|
||||||
return boost::beast::buffers_to_string(std::move(buffer).data());
|
return boost::beast::buffers_to_string(std::move(buffer).data());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/MockOperation.hpp"
|
#include "util/MockOperation.hpp"
|
||||||
#include "util/MockStopToken.hpp"
|
#include "util/MockStopToken.hpp"
|
||||||
#include "util/MockStrand.hpp"
|
#include "util/MockStrand.hpp"
|
||||||
@@ -30,12 +29,13 @@
|
|||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <expected>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
struct MockExecutionContext {
|
struct MockExecutionContext {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using ValueType = util::Expected<T, util::async::ExecutionError>;
|
using ValueType = std::expected<T, util::async::ExecutionError>;
|
||||||
|
|
||||||
using StopSource = MockStopSource;
|
using StopSource = MockStopSource;
|
||||||
using StopToken = MockStopToken;
|
using StopToken = MockStopToken;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/MockOperation.hpp"
|
#include "util/MockOperation.hpp"
|
||||||
#include "util/async/AnyStopToken.hpp"
|
#include "util/async/AnyStopToken.hpp"
|
||||||
#include "util/async/Error.hpp"
|
#include "util/async/Error.hpp"
|
||||||
@@ -28,12 +27,13 @@
|
|||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <expected>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
struct MockStrand {
|
struct MockStrand {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using ValueType = util::Expected<T, util::async::ExecutionError>;
|
using ValueType = std::expected<T, util::async::ExecutionError>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using Operation = MockOperation<T>;
|
using Operation = MockOperation<T>;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "util/TestWsServer.hpp"
|
#include "util/TestWsServer.hpp"
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
@@ -38,6 +37,7 @@
|
|||||||
#include <boost/beast/websocket/stream_base.hpp>
|
#include <boost/beast/websocket/stream_base.hpp>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -91,7 +91,7 @@ TestWsServer::TestWsServer(asio::io_context& context, std::string const& host, i
|
|||||||
acceptor_.bind(endpoint);
|
acceptor_.bind(endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Expected<TestWsConnection, util::requests::RequestError>
|
std::expected<TestWsConnection, util::requests::RequestError>
|
||||||
TestWsServer::acceptConnection(asio::yield_context yield)
|
TestWsServer::acceptConnection(asio::yield_context yield)
|
||||||
{
|
{
|
||||||
acceptor_.listen(asio::socket_base::max_listen_connections);
|
acceptor_.listen(asio::socket_base::max_listen_connections);
|
||||||
@@ -100,13 +100,13 @@ TestWsServer::acceptConnection(asio::yield_context yield)
|
|||||||
asio::ip::tcp::socket socket(acceptor_.get_executor());
|
asio::ip::tcp::socket socket(acceptor_.get_executor());
|
||||||
acceptor_.async_accept(socket, yield[errorCode]);
|
acceptor_.async_accept(socket, yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return util::Unexpected{util::requests::RequestError{"Accept error", errorCode}};
|
return std::unexpected{util::requests::RequestError{"Accept error", errorCode}};
|
||||||
|
|
||||||
boost::beast::websocket::stream<boost::beast::tcp_stream> ws(std::move(socket));
|
boost::beast::websocket::stream<boost::beast::tcp_stream> ws(std::move(socket));
|
||||||
ws.set_option(websocket::stream_base::timeout::suggested(boost::beast::role_type::server));
|
ws.set_option(websocket::stream_base::timeout::suggested(boost::beast::role_type::server));
|
||||||
ws.async_accept(yield[errorCode]);
|
ws.async_accept(yield[errorCode]);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return util::Unexpected{util::requests::RequestError{"Handshake error", errorCode}};
|
return std::unexpected{util::requests::RequestError{"Handshake error", errorCode}};
|
||||||
|
|
||||||
return TestWsConnection(std::move(ws));
|
return TestWsConnection(std::move(ws));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
|
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
@@ -28,6 +27,7 @@
|
|||||||
#include <boost/beast/core/tcp_stream.hpp>
|
#include <boost/beast/core/tcp_stream.hpp>
|
||||||
#include <boost/beast/websocket/stream.hpp>
|
#include <boost/beast/websocket/stream.hpp>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -59,7 +59,7 @@ class TestWsServer {
|
|||||||
public:
|
public:
|
||||||
TestWsServer(boost::asio::io_context& context, std::string const& host, int port);
|
TestWsServer(boost::asio::io_context& context, std::string const& host, int port);
|
||||||
|
|
||||||
util::Expected<TestWsConnection, util::requests::RequestError>
|
std::expected<TestWsConnection, util::requests::RequestError>
|
||||||
acceptConnection(boost::asio::yield_context yield);
|
acceptConnection(boost::asio::yield_context yield);
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/MockOperation.hpp"
|
#include "util/MockOperation.hpp"
|
||||||
#include "util/async/AnyOperation.hpp"
|
#include "util/async/AnyOperation.hpp"
|
||||||
#include "util/async/Error.hpp"
|
#include "util/async/Error.hpp"
|
||||||
@@ -26,14 +25,15 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <any>
|
#include <any>
|
||||||
|
#include <expected>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace util::async;
|
using namespace util::async;
|
||||||
using namespace ::testing;
|
using namespace ::testing;
|
||||||
|
|
||||||
struct AnyOperationTests : Test {
|
struct AnyOperationTests : Test {
|
||||||
using OperationType = MockOperation<util::Expected<impl::Any, ExecutionError>>;
|
using OperationType = MockOperation<std::expected<impl::Any, ExecutionError>>;
|
||||||
using ScheduledOperationType = MockScheduledOperation<util::Expected<impl::Any, ExecutionError>>;
|
using ScheduledOperationType = MockScheduledOperation<std::expected<impl::Any, ExecutionError>>;
|
||||||
|
|
||||||
NaggyMock<OperationType> mockOp;
|
NaggyMock<OperationType> mockOp;
|
||||||
NaggyMock<ScheduledOperationType> mockScheduledOp;
|
NaggyMock<ScheduledOperationType> mockScheduledOp;
|
||||||
@@ -46,7 +46,7 @@ using AnyOperationDeathTest = AnyOperationTests;
|
|||||||
|
|
||||||
TEST_F(AnyOperationTests, VoidDataYieldsNoError)
|
TEST_F(AnyOperationTests, VoidDataYieldsNoError)
|
||||||
{
|
{
|
||||||
auto const noError = util::Expected<impl::Any, ExecutionError>(impl::Any{});
|
auto const noError = std::expected<impl::Any, ExecutionError>(impl::Any{});
|
||||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(noError));
|
EXPECT_CALL(mockOp, get()).WillOnce(Return(noError));
|
||||||
auto res = voidOp.get();
|
auto res = voidOp.get();
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
@@ -85,7 +85,7 @@ TEST_F(AnyOperationTests, RequestStopCallPropagated)
|
|||||||
|
|
||||||
TEST_F(AnyOperationTests, GetPropagatesError)
|
TEST_F(AnyOperationTests, GetPropagatesError)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(util::Unexpected(ExecutionError{"tid", "Not good"})));
|
EXPECT_CALL(mockOp, get()).WillOnce(Return(std::unexpected(ExecutionError{"tid", "Not good"})));
|
||||||
auto res = intOp.get();
|
auto res = intOp.get();
|
||||||
ASSERT_FALSE(res);
|
ASSERT_FALSE(res);
|
||||||
EXPECT_TRUE(res.error().message.ends_with("Not good"));
|
EXPECT_TRUE(res.error().message.ends_with("Not good"));
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/MockOperation.hpp"
|
#include "util/MockOperation.hpp"
|
||||||
#include "util/MockStrand.hpp"
|
#include "util/MockStrand.hpp"
|
||||||
#include "util/async/AnyOperation.hpp"
|
#include "util/async/AnyOperation.hpp"
|
||||||
@@ -29,6 +28,7 @@
|
|||||||
|
|
||||||
#include <any>
|
#include <any>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <expected>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/Fixtures.hpp"
|
#include "util/Fixtures.hpp"
|
||||||
#include "util/TestHttpServer.hpp"
|
#include "util/TestHttpServer.hpp"
|
||||||
#include "util/requests/RequestBuilder.hpp"
|
#include "util/requests/RequestBuilder.hpp"
|
||||||
@@ -32,6 +31,7 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <expected>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@@ -111,14 +111,14 @@ TEST_P(RequestBuilderTest, SimpleRequest)
|
|||||||
);
|
);
|
||||||
|
|
||||||
runSpawn([this, replyBody](asio::yield_context yield) {
|
runSpawn([this, replyBody](asio::yield_context yield) {
|
||||||
auto const response = [&]() -> util::Expected<std::string, RequestError> {
|
auto const response = [&]() -> std::expected<std::string, RequestError> {
|
||||||
switch (GetParam().method) {
|
switch (GetParam().method) {
|
||||||
case http::verb::get:
|
case http::verb::get:
|
||||||
return builder.getPlain(yield);
|
return builder.getPlain(yield);
|
||||||
case http::verb::post:
|
case http::verb::post:
|
||||||
return builder.postPlain(yield);
|
return builder.postPlain(yield);
|
||||||
default:
|
default:
|
||||||
return util::Unexpected{RequestError{"Invalid HTTP verb"}};
|
return std::unexpected{RequestError{"Invalid HTTP verb"}};
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
ASSERT_TRUE(response) << response.error().message();
|
ASSERT_TRUE(response) << response.error().message();
|
||||||
@@ -243,14 +243,14 @@ TEST_P(RequestBuilderSslTest, TrySslUsePlain)
|
|||||||
);
|
);
|
||||||
|
|
||||||
runSpawn([this](asio::yield_context yield) {
|
runSpawn([this](asio::yield_context yield) {
|
||||||
auto const response = [&]() -> util::Expected<std::string, RequestError> {
|
auto const response = [&]() -> std::expected<std::string, RequestError> {
|
||||||
switch (GetParam().method) {
|
switch (GetParam().method) {
|
||||||
case http::verb::get:
|
case http::verb::get:
|
||||||
return builder.get(yield);
|
return builder.get(yield);
|
||||||
case http::verb::post:
|
case http::verb::post:
|
||||||
return builder.post(yield);
|
return builder.post(yield);
|
||||||
default:
|
default:
|
||||||
return util::Unexpected{RequestError{"Invalid HTTP verb"}};
|
return std::unexpected{RequestError{"Invalid HTTP verb"}};
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
ASSERT_TRUE(response) << response.error().message();
|
ASSERT_TRUE(response) << response.error().message();
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include "util/Expected.hpp"
|
|
||||||
#include "util/Fixtures.hpp"
|
#include "util/Fixtures.hpp"
|
||||||
#include "util/TestWsServer.hpp"
|
#include "util/TestWsServer.hpp"
|
||||||
#include "util/requests/Types.hpp"
|
#include "util/requests/Types.hpp"
|
||||||
@@ -29,6 +28,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <expected>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@@ -44,7 +44,7 @@ struct WsConnectionTestsBase : SyncAsioContextTest {
|
|||||||
|
|
||||||
template <typename T, typename E>
|
template <typename T, typename E>
|
||||||
T
|
T
|
||||||
unwrap(util::Expected<T, E> expected)
|
unwrap(std::expected<T, E> expected)
|
||||||
{
|
{
|
||||||
[&]() { ASSERT_TRUE(expected.has_value()) << expected.error().message(); }();
|
[&]() { ASSERT_TRUE(expected.has_value()) << expected.error().message(); }();
|
||||||
return std::move(expected).value();
|
return std::move(expected).value();
|
||||||
|
|||||||
Reference in New Issue
Block a user