Addded Romeo that generates some doc. WIP.
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user