WIP: CURL/request implementation.
This commit is contained in:
parent
4e93898a56
commit
92d7b5552f
134
source/mijin/net/curl_wrappers.hpp
Normal file
134
source/mijin/net/curl_wrappers.hpp
Normal file
@ -0,0 +1,134 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_NET_CURL_WRAPPERS_HPP_INCLUDED)
|
||||
#define MIJIN_NET_CURL_WRAPPERS_HPP_INCLUDED 1
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "./url.hpp"
|
||||
#include "../debug/assert.hpp"
|
||||
#include "../internal/common.hpp"
|
||||
#include "../types/result.hpp"
|
||||
|
||||
namespace curl
|
||||
{
|
||||
#if !MIJIN_WITH_EXCEPTIONS
|
||||
struct [[nodiscard]] Error
|
||||
{
|
||||
CURLcode code = CURLE_OK;
|
||||
|
||||
[[nodiscard]]
|
||||
bool isSuccess() const MIJIN_NOEXCEPT { return code == CURLE_OK; }
|
||||
};
|
||||
|
||||
#define MIJIN_CURL_VERIFY_RESULT(curlResult) \
|
||||
do \
|
||||
{ \
|
||||
if ((curlResult) != CURLE_OK) \
|
||||
{ \
|
||||
return Error{curlResult}; \
|
||||
} \
|
||||
} while (0)
|
||||
#define MIJIN_CURL_RETURN_SUCCESS() return Error()
|
||||
#else
|
||||
using Error = void;
|
||||
|
||||
[[nodiscard]]
|
||||
std::string curlCodeMessage(CURLcode code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
default:
|
||||
return "Unknown CURL error.";
|
||||
}
|
||||
}
|
||||
|
||||
class CurlException : public std::runtime_error
|
||||
{
|
||||
private:
|
||||
CURLcode code_;
|
||||
public:
|
||||
explicit CurlException(CURLcode code) MIJIN_NOEXCEPT: std::runtime_error(curlCodeMessage(code)), code_(code)
|
||||
{}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr CURLcode getCode() const MIJIN_NOEXCEPT
|
||||
{ return code_; }
|
||||
};
|
||||
|
||||
#define MIJIN_CURL_VERIFY_RESULT(curlResult) \
|
||||
do \
|
||||
{ \
|
||||
if ((curlResult) != CURLE_OK) \
|
||||
{ \
|
||||
throw CurlException((curlResult)); \
|
||||
} \
|
||||
} while (0)
|
||||
#define MIJIN_CURL_RETURN_SUCCESS() return
|
||||
#endif
|
||||
|
||||
class CurlEasy
|
||||
{
|
||||
private:
|
||||
CURL* handle_ = nullptr;
|
||||
public:
|
||||
CurlEasy() MIJIN_NOEXCEPT = default;
|
||||
CurlEasy(const CurlEasy&) = delete;
|
||||
CurlEasy(CurlEasy&& other) MIJIN_NOEXCEPT : handle_(std::exchange(other.handle_, nullptr)) {}
|
||||
~CurlEasy() MIJIN_NOEXCEPT
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
CurlEasy& operator=(const CurlEasy&) = delete;
|
||||
CurlEasy& operator=(CurlEasy&& other) MIJIN_NOEXCEPT
|
||||
{
|
||||
if (this == &other)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
reset();
|
||||
handle_ = std::exchange(other.handle_, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MIJIN_ERROR_BOOL init() MIJIN_THROWS
|
||||
{
|
||||
reset();
|
||||
handle_ = curl_easy_init();
|
||||
if (handle_ != nullptr)
|
||||
{
|
||||
MIJIN_THROW_OR_RETURN_STD(false, "Error initializing CURL easy.");
|
||||
}
|
||||
MIJIN_RETURN_SUCCESS(true);
|
||||
}
|
||||
void reset() MIJIN_NOEXCEPT
|
||||
{
|
||||
if (handle_)
|
||||
{
|
||||
curl_easy_cleanup(handle_);
|
||||
handle_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Error setURL(const char* url) MIJIN_THROWS
|
||||
{
|
||||
const CURLcode result = curl_easy_setopt(handle_, CURLOPT_URL, url);
|
||||
MIJIN_CURL_VERIFY_RESULT(result);
|
||||
MIJIN_CURL_RETURN_SUCCESS();
|
||||
}
|
||||
|
||||
Error setURL(const std::string& url) MIJIN_NOEXCEPT
|
||||
{
|
||||
return setURL(url.c_str());
|
||||
}
|
||||
|
||||
Error setURL(const mijin::URL& url) MIJIN_NOEXCEPT
|
||||
{
|
||||
return setURL(url.getBase().c_str());
|
||||
}
|
||||
};
|
||||
} // namespace curl
|
||||
|
||||
#endif // !defined(MIJIN_NET_CURL_WRAPPERS_HPP_INCLUDED)
|
60
source/mijin/net/request.cpp
Normal file
60
source/mijin/net/request.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
|
||||
#include "./request.hpp"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "./curl_wrappers.hpp"
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool gCurlInited = false;
|
||||
std::mutex gCurlInitMutex;
|
||||
|
||||
class CURLGuard
|
||||
{
|
||||
public:
|
||||
~CURLGuard() MIJIN_NOEXCEPT
|
||||
{
|
||||
if (gCurlInited)
|
||||
{
|
||||
curl_global_cleanup();
|
||||
}
|
||||
}
|
||||
} gCURLGuard [[maybe_unused]];
|
||||
|
||||
bool initCURL() MIJIN_NOEXCEPT
|
||||
{
|
||||
if (gCurlInited)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const std::unique_lock initLock(gCurlInitMutex);
|
||||
if (gCurlInited)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
gCurlInited = (curl_global_init(0) == CURLE_OK);
|
||||
return gCurlInited;
|
||||
}
|
||||
}
|
||||
|
||||
Task<StreamResult<HTTPResponse>> c_request(const URL& url, HTTPRequest request) MIJIN_NOEXCEPT
|
||||
{
|
||||
(void) url;
|
||||
(void) request;
|
||||
if (!initCURL())
|
||||
{
|
||||
co_return StreamError::UNKNOWN_ERROR;
|
||||
}
|
||||
curl::CurlEasy easy;
|
||||
if (!easy.init())
|
||||
{
|
||||
co_return StreamError::UNKNOWN_ERROR;
|
||||
}
|
||||
easy.setURL(url);
|
||||
|
||||
co_return StreamError::UNKNOWN_ERROR;
|
||||
}
|
||||
} // namespace mijin
|
15
source/mijin/net/request.hpp
Normal file
15
source/mijin/net/request.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_NET_REQUST_HPP_INCLUDED)
|
||||
#define MIJIN_NET_REQUST_HPP_INCLUDED 1
|
||||
|
||||
#include "./http.hpp"
|
||||
#include "../internal/common.hpp"
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
Task<StreamResult<HTTPResponse>> c_request(const URL& url, HTTPRequest request = {}) MIJIN_NOEXCEPT;
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_NET_REQUST_HPP_INCLUDED)
|
Loading…
x
Reference in New Issue
Block a user