C3/Src/Common/FSecure/WinHttp/HttpClient.h

59 lines
1.9 KiB
C++

#pragma once
#include "HttpRequest.h"
#include "Handles/HttpSession.h"
#include "Handles/HttpConnection.h"
#include "Uri.h"
namespace FSecure::WinHttp
{
/// HTTP client class with API simmilar to cpprestsdk's http_client
class HttpClient
{
public:
/// Create HTTP clinet
/// @param uri - base or full uri
/// @param proxy - proxy settings
/// @throws std::runtime_error if underlying HTTP session fails
HttpClient(Uri uri, WebProxy proxy = {})
: m_ProxyConfig{std::move(proxy)}
, m_Session{ m_ProxyConfig }
, m_Uri(std::move(uri))
{
m_Connection = m_Session.Connect(m_Uri.GetHostName(), m_Uri.GetPort(), m_Uri.UseHttps());
}
/// Send HTTP request
/// @param request - request to send
/// @param content type - optional content type (override content type from `request`)
/// @param data - optional request body (override request body from `request`)
/// @returns HttpResponse
/// @throws std::runtime_error
HttpResponse Request(HttpRequest const& request, std::wstring const& contentType = {}, std::vector<uint8_t> const& data = {})
{
auto coalesce = [](auto&& opt1, auto&& defaultValue) { return !opt1.empty() ? opt1 : defaultValue; };
auto const& path = coalesce(request.m_Path, m_Uri.GetPathWithQuery());
auto req = m_Connection.OpenRequest(GetMethodString(request.m_Method), path);
req.SetTimeout(request.m_ResolveTimeout, request.m_ConnectTimeout, request.m_SendTimeout, request.m_ReceiveTimeout);
for (auto& [name, content] : request.m_Headers)
req.SetHeader(name, content);
if (auto proxy = m_Session.GetProxyForUrl(m_Uri))
req.SetProxy(*proxy);
auto const& xContentType = coalesce(request.m_ContentType, contentType);
auto const& xData = coalesce(request.m_Data, data);
req.Send(xContentType, xData);
return req.ReceiveResponse();
}
private:
WebProxy m_ProxyConfig;
HttpSession m_Session;
Uri m_Uri;
HttpConnection m_Connection;
};
}