197 lines
6.3 KiB
C++
197 lines
6.3 KiB
C++
#include "HttpClient.h"
|
|
#include <Windows.h>
|
|
#include <winhttp.h>
|
|
#include <Core/Memory/MemoryArena.h>
|
|
#include <Core/Common/CoreUtils.h>
|
|
|
|
namespace Romeo
|
|
{
|
|
static wchar_t* ConvertToWide(Juliet::Arena* arena, const Juliet::String& str)
|
|
{
|
|
Assert(arena != nullptr);
|
|
if (str.Size == 0)
|
|
{
|
|
return const_cast<wchar_t*>(L"");
|
|
}
|
|
int wLen = MultiByteToWideChar(CP_UTF8, 0, CStr(str), static_cast<int>(str.Size), nullptr, 0);
|
|
if (wLen <= 0)
|
|
{
|
|
return const_cast<wchar_t*>(L"");
|
|
}
|
|
wchar_t* wBuf = Juliet::ArenaPushArray<wchar_t>(arena, static_cast<size_t>(wLen + 1) JULIET_DEBUG_PARAM("WideStr"));
|
|
MultiByteToWideChar(CP_UTF8, 0, CStr(str), static_cast<int>(str.Size), wBuf, wLen);
|
|
wBuf[wLen] = L'\0';
|
|
return wBuf;
|
|
}
|
|
|
|
bool HttpClient::Post(
|
|
Juliet::Arena* arena,
|
|
const Juliet::String& host,
|
|
int port,
|
|
const Juliet::String& path,
|
|
bool isHttps,
|
|
const Juliet::String& requestBody,
|
|
Juliet::String& outResponse
|
|
)
|
|
{
|
|
Assert(arena != nullptr);
|
|
Assert(host.Size > 0);
|
|
|
|
bool success = false;
|
|
HINTERNET hSession = nullptr;
|
|
HINTERNET hConnect = nullptr;
|
|
HINTERNET hRequest = nullptr;
|
|
|
|
hSession = WinHttpOpen(
|
|
L"Romeo/1.0",
|
|
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
|
nullptr,
|
|
nullptr,
|
|
0
|
|
);
|
|
|
|
if (hSession != nullptr)
|
|
{
|
|
WinHttpSetTimeouts(hSession, 60000, 60000, 60000, 1800000);
|
|
wchar_t* wHost = ConvertToWide(arena, host);
|
|
hConnect = WinHttpConnect(
|
|
hSession,
|
|
wHost,
|
|
static_cast<INTERNET_PORT>(port),
|
|
0
|
|
);
|
|
}
|
|
|
|
if (hConnect != nullptr)
|
|
{
|
|
wchar_t* wPath = ConvertToWide(arena, path);
|
|
hRequest = WinHttpOpenRequest(
|
|
hConnect,
|
|
L"POST",
|
|
wPath,
|
|
nullptr,
|
|
nullptr,
|
|
nullptr,
|
|
isHttps ? WINHTTP_FLAG_SECURE : 0
|
|
);
|
|
}
|
|
|
|
if (hRequest != nullptr)
|
|
{
|
|
const wchar_t* headers = L"Content-Type: application/json\r\n";
|
|
DWORD headersLen = static_cast<DWORD>(-1);
|
|
|
|
BOOL sendRes = WinHttpSendRequest(
|
|
hRequest,
|
|
headers,
|
|
headersLen,
|
|
const_cast<char*>(CStr(requestBody)),
|
|
static_cast<DWORD>(requestBody.Size),
|
|
static_cast<DWORD>(requestBody.Size),
|
|
0
|
|
);
|
|
|
|
if (sendRes != 0)
|
|
{
|
|
BOOL recvRes = WinHttpReceiveResponse(hRequest, nullptr);
|
|
if (recvRes != 0)
|
|
{
|
|
DWORD dwSize = 0;
|
|
DWORD dwDownloaded = 0;
|
|
|
|
size_t totalBytes = 0;
|
|
size_t capacity = 1024;
|
|
char* responseData = Juliet::ArenaPushArray<char>(arena, capacity JULIET_DEBUG_PARAM("HttpResponse"));
|
|
|
|
do
|
|
{
|
|
dwSize = 0;
|
|
if (WinHttpQueryDataAvailable(hRequest, &dwSize) == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (dwSize == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (totalBytes + dwSize >= capacity)
|
|
{
|
|
size_t newCapacity = capacity * 2;
|
|
if (newCapacity < totalBytes + dwSize + 1)
|
|
{
|
|
newCapacity = totalBytes + dwSize + 1;
|
|
}
|
|
|
|
char* newBuf = Juliet::ArenaPushArray<char>(arena, newCapacity JULIET_DEBUG_PARAM("HttpResponseGrow"));
|
|
memcpy(newBuf, responseData, totalBytes);
|
|
responseData = newBuf;
|
|
capacity = newCapacity;
|
|
}
|
|
|
|
dwDownloaded = 0;
|
|
if (WinHttpReadData(hRequest, responseData + totalBytes, dwSize, &dwDownloaded) != 0)
|
|
{
|
|
totalBytes += dwDownloaded;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
} while (dwSize > 0);
|
|
|
|
DWORD dwStatusCode = 0;
|
|
DWORD dwHeaderSize = sizeof(dwStatusCode);
|
|
WinHttpQueryHeaders(
|
|
hRequest,
|
|
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
|
|
nullptr,
|
|
&dwStatusCode,
|
|
&dwHeaderSize,
|
|
nullptr
|
|
);
|
|
|
|
if (dwStatusCode == 200)
|
|
{
|
|
if (totalBytes > 0)
|
|
{
|
|
responseData[totalBytes] = '\0';
|
|
outResponse.Data = responseData;
|
|
outResponse.Size = totalBytes;
|
|
success = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (totalBytes > 0)
|
|
{
|
|
responseData[totalBytes] = '\0';
|
|
printf("Romeo HttpClient: HTTP Error Status %u. Response: %s\n", static_cast<unsigned int>(dwStatusCode), responseData);
|
|
}
|
|
else
|
|
{
|
|
printf("Romeo HttpClient: HTTP Error Status %u. Empty response.\n", static_cast<unsigned int>(dwStatusCode));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hRequest != nullptr)
|
|
{
|
|
WinHttpCloseHandle(hRequest);
|
|
}
|
|
if (hConnect != nullptr)
|
|
{
|
|
WinHttpCloseHandle(hConnect);
|
|
}
|
|
if (hSession != nullptr)
|
|
{
|
|
WinHttpCloseHandle(hSession);
|
|
}
|
|
|
|
return success;
|
|
}
|
|
}
|