libcpr/include/cpr/multiperform.h
2024-04-13 21:01:22 -04:00

137 lines
4.7 KiB
C++

#ifndef CPR_MULTIPERFORM_H
#define CPR_MULTIPERFORM_H
#include "cpr/curlmultiholder.h"
#include "cpr/response.h"
#include "cpr/session.h"
#include <functional>
#include <memory>
#include <queue>
#include <stdexcept>
#include <vector>
namespace cpr {
class InterceptorMulti;
class MultiPerform {
public:
enum class HttpMethod {
UNDEFINED = 0,
GET_REQUEST,
POST_REQUEST,
PUT_REQUEST,
DELETE_REQUEST,
PATCH_REQUEST,
HEAD_REQUEST,
OPTIONS_REQUEST,
DOWNLOAD_REQUEST,
};
MultiPerform();
MultiPerform(const MultiPerform& other) = delete;
MultiPerform(MultiPerform&& old) = default;
~MultiPerform();
MultiPerform& operator=(const MultiPerform& other) = delete;
MultiPerform& operator=(MultiPerform&& old) noexcept = default;
std::vector<Response> Get();
std::vector<Response> Delete();
template <typename... DownloadArgTypes>
std::vector<Response> Download(DownloadArgTypes... args);
std::vector<Response> Put();
std::vector<Response> Head();
std::vector<Response> Options();
std::vector<Response> Patch();
std::vector<Response> Post();
std::vector<Response> Perform();
template <typename... DownloadArgTypes>
std::vector<Response> PerformDownload(DownloadArgTypes... args);
void AddSession(std::shared_ptr<Session>& session, HttpMethod method = HttpMethod::UNDEFINED);
void RemoveSession(const std::shared_ptr<Session>& session);
std::vector<std::pair<std::shared_ptr<Session>, HttpMethod>>& GetSessions();
[[nodiscard]] const std::vector<std::pair<std::shared_ptr<Session>, HttpMethod>>& GetSessions() const;
void AddInterceptor(const std::shared_ptr<InterceptorMulti>& pinterceptor);
private:
// Interceptors should be able to call the private proceed() and PrepareDownloadSessions() functions
friend InterceptorMulti;
void SetHttpMethod(HttpMethod method);
void PrepareSessions();
template <typename CurrentDownloadArgType, typename... DownloadArgTypes>
void PrepareDownloadSessions(size_t sessions_index, CurrentDownloadArgType current_arg, DownloadArgTypes... args);
template <typename CurrentDownloadArgType>
void PrepareDownloadSessions(size_t sessions_index, CurrentDownloadArgType current_arg);
void PrepareDownloadSession(size_t sessions_index, std::ofstream& file);
void PrepareDownloadSession(size_t sessions_index, const WriteCallback& write);
void PrepareGet();
void PrepareDelete();
void PreparePut();
void PreparePatch();
void PrepareHead();
void PrepareOptions();
void PreparePost();
template <typename... DownloadArgTypes>
void PrepareDownload(DownloadArgTypes... args);
std::vector<Response> intercept();
std::vector<Response> proceed();
std::vector<Response> MakeRequest();
std::vector<Response> MakeDownloadRequest();
void DoMultiPerform();
std::vector<Response> ReadMultiInfo(std::function<Response(Session&, CURLcode)>&& complete_function);
std::vector<std::pair<std::shared_ptr<Session>, HttpMethod>> sessions_;
std::unique_ptr<CurlMultiHolder> multicurl_;
bool is_download_multi_perform{false};
std::queue<std::shared_ptr<InterceptorMulti>> interceptors_;
};
template <typename CurrentDownloadArgType>
void MultiPerform::PrepareDownloadSessions(size_t sessions_index, CurrentDownloadArgType current_arg) {
PrepareDownloadSession(sessions_index, current_arg);
}
template <typename CurrentDownloadArgType, typename... DownloadArgTypes>
void MultiPerform::PrepareDownloadSessions(size_t sessions_index, CurrentDownloadArgType current_arg, DownloadArgTypes... args) {
PrepareDownloadSession(sessions_index, current_arg);
PrepareDownloadSessions<DownloadArgTypes...>(sessions_index + 1, args...);
}
template <typename... DownloadArgTypes>
void MultiPerform::PrepareDownload(DownloadArgTypes... args) {
SetHttpMethod(HttpMethod::DOWNLOAD_REQUEST);
PrepareDownloadSessions<DownloadArgTypes...>(0, args...);
}
template <typename... DownloadArgTypes>
std::vector<Response> MultiPerform::Download(DownloadArgTypes... args) {
if (sizeof...(args) != sessions_.size()) {
throw std::invalid_argument("Number of download arguments has to match the number of sessions added to the multiperform!");
}
PrepareDownload(args...);
return MakeDownloadRequest();
}
template <typename... DownloadArgTypes>
std::vector<Response> MultiPerform::PerformDownload(DownloadArgTypes... args) {
if (sizeof...(args) != sessions_.size()) {
throw std::invalid_argument("Number of download arguments has to match the number of sessions added to the multiperform!");
}
PrepareDownloadSessions<DownloadArgTypes...>(0, args...);
return MakeDownloadRequest();
}
} // namespace cpr
#endif