Add APIRequest class to aid with making API requests.

This commit is contained in:
Mm2PL 2022-09-16 23:18:04 +02:00
parent c6ebb70e05
commit f7194e820c
No known key found for this signature in database
GPG key ID: 94AC9B80EFA15ED9

115
src/common/APIRequest.hpp Normal file
View file

@ -0,0 +1,115 @@
#pragma once
#include <functional>
#include "common/NetworkCommon.hpp"
#include "common/NetworkRequest.hpp"
#include "common/NetworkResult.hpp"
#include "common/Outcome.hpp"
namespace chatterino {
// i can't make it not pass something, so this is a small type that does nothing
struct APIRequestNoErrorValue {
};
template <typename OkType, typename ErrorType>
class APIRequestData
{
using APISuceessCallback = std::function<Outcome(NetworkResult, OkType)>;
using APIErrorCallback = std::function<void(NetworkResult, ErrorType)>;
using APIFinallyCallback = std::function<void()>;
public:
APISuceessCallback onSuccess;
APIErrorCallback onError;
APIFinallyCallback finally;
};
template <typename OkType, typename ErrorType>
class APIRequest
{
using APISuceessCallback = std::function<Outcome(NetworkResult, OkType)>;
using APIErrorCallback = std::function<void(NetworkResult, ErrorType)>;
using APIFinallyCallback = std::function<void()>;
private:
NetworkRequest underlying_;
std::shared_ptr<APIRequestData<OkType, ErrorType>> data_;
public:
// move = good
APIRequest(APIRequest<OkType, ErrorType> &&other) = default;
APIRequest &operator=(APIRequest<OkType, ErrorType> &&other) = default;
// copy = bad
APIRequest(const APIRequest<OkType, ErrorType> &other) = delete;
APIRequest &operator=(const APIRequest<OkType, ErrorType> &other) = delete;
explicit APIRequest(
QUrl url, NetworkRequestType requestType,
std::function<OkType(NetworkResult)> successTransformer,
std::function<ErrorType(NetworkResult)> errorTransformer = nullptr,
std::function<void()> onFinally = nullptr)
: underlying_(std::move(url), requestType)
, data_(std::make_shared<APIRequestData<OkType, ErrorType>>())
{
auto data = this->data_;
this->underlying_ =
std::move(this->underlying_)
.timeout(5 * 1000)
.onSuccess(
[data, successTransformer](NetworkResult res) -> Outcome {
OkType val = successTransformer(res);
return data->onSuccess(res, val);
})
.onError([data, errorTransformer](NetworkResult res) {
if (errorTransformer)
{
ErrorType err = errorTransformer(res);
data->onError(res, err);
}
})
.finally([data, onFinally]() {
if (onFinally)
{
onFinally();
}
if (data->finally)
{
data->finally();
}
});
};
APIRequest<OkType, ErrorType> header(const char *headerName,
const char *value) &&
{
this->underlying_ =
std::move(this->underlying_).header(headerName, value);
return std::move(*this);
}
APIRequest<OkType, ErrorType> onError(APIErrorCallback cb) &&
{
this->data_->onError = cb;
return std::move(*this);
};
APIRequest<OkType, ErrorType> onSuccess(APISuceessCallback cb) &&
{
this->data_->onSuccess = cb;
return std::move(*this);
};
APIRequest<OkType, ErrorType> finally(APIFinallyCallback cb) &&
{
this->data_->finally = cb;
return std::move(*this);
};
void execute()
{
this->underlying_.execute();
}
};
} // namespace chatterino