WinHTTP - HTTP Communication
Structure of the HTTP Response
C
typedef struct {
DWORD statusCode;
char *responseText;
} HTTPResponse;
Source
C
HTTPResponse SendHttpRequest(const char *url, const char *urlpath, const char *post_data, const char *headers, BOOL ssl,
BOOL is_post) {
HTTPResponse response;
response.statusCode = 0;
response.responseText = NULL;
HINTERNET hSession = WinHttpOpen(L"Client App/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
if (!hSession) {
response.statusCode = 1;
return response;
}
URL_COMPONENTS urlComp;
memset(&urlComp, 0, sizeof(urlComp));
urlComp.dwStructSize = sizeof(urlComp);
WCHAR hostname[256];
WCHAR path[1024];
urlComp.lpszHostName = hostname;
urlComp.dwHostNameLength = sizeof(hostname) / sizeof(WCHAR);
urlComp.lpszUrlPath = path;
urlComp.dwUrlPathLength = sizeof(path) / sizeof(WCHAR);
int urlLength = _MultiByteToWideChar(0, 0, url, -1, NULL, 0);
WCHAR *wideUrl = (WCHAR *) malloc(urlLength * sizeof(WCHAR));
_MultiByteToWideChar(0, 0, url, -1, wideUrl, urlLength);
if (!WinHttpCrackUrl(wideUrl, (DWORD) wcslen(wideUrl), 0, &urlComp)) {
free(wideUrl);
WinHttpCloseHandle(hSession);
response.statusCode = 2;
return response;
}
free(wideUrl);
HINTERNET hConnect = WinHttpConnect(hSession, urlComp.lpszHostName, urlComp.nPort, 0);
if (!hConnect) {
WinHttpCloseHandle(hSession);
response.statusCode = 3;
return response;
}
int urlpathLength = _MultiByteToWideChar(0, 0, urlpath, -1, NULL, 0);
WCHAR *wideUrlPath = (WCHAR *) malloc(urlpathLength * sizeof(WCHAR));
_MultiByteToWideChar(0, 0, urlpath, -1, wideUrlPath, urlpathLength);
LPCWSTR pwszVerb = is_post ? L"POST" : L"GET";
HINTERNET hRequest = WinHttpOpenRequest(hConnect, pwszVerb, wideUrlPath, NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES, ssl ? WINHTTP_FLAG_SECURE : 0);
free(wideUrlPath);
if (!hRequest) {
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
response.statusCode = 4;
return response;
}
int headersLength = _MultiByteToWideChar(0, 0, headers, -1, NULL, 0);
WCHAR *wideHeaders = (WCHAR *) malloc(headersLength * sizeof(WCHAR));
_MultiByteToWideChar(0, 0, headers, -1, wideHeaders, headersLength);
BOOL bResults;
if (is_post) {
bResults = WinHttpSendRequest(hRequest, wideHeaders, 0, (LPVOID) post_data, (DWORD) strlen(post_data),
(DWORD) strlen(post_data), 0);
} else {
bResults = WinHttpSendRequest(hRequest, wideHeaders, 0, NULL, 0, 0, 0);
}
if (!bResults) {
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
response.statusCode = 5;
return response;
}
bResults = WinHttpReceiveResponse(hRequest, NULL);
if (!bResults) {
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
response.statusCode = 6;
return response;
}
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
DWORD totalSize = 0;
LPSTR responseText = (LPSTR) malloc(1);
*responseText = '\0';
do {
if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) break;
pszOutBuffer = (LPSTR) malloc(dwSize + 1);
if (!pszOutBuffer) break;
RtlZeroMemory(pszOutBuffer, dwSize + 1);
if (!WinHttpReadData(hRequest, (LPVOID) pszOutBuffer, dwSize, &dwDownloaded)) {
free(pszOutBuffer);
break;
}
// Increase totalSize for realloc
LPSTR newBuffer = (LPSTR) realloc(responseText, totalSize + dwDownloaded + 1);
if (!newBuffer) {
free(pszOutBuffer);
break;
}
responseText = newBuffer;
memcpy(responseText + totalSize, pszOutBuffer, dwDownloaded);
totalSize += dwDownloaded;
responseText[totalSize] = '\0'; // null-terminate
free(pszOutBuffer);
} while (dwSize > 0);
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
response.statusCode = 200;
response.responseText = responseText;
return response;
}
HTTPResponse SendGet(const char *url, const char *urlpath, const char *headers, BOOL ssl) {
return SendHttpRequest(url, urlpath, NULL, headers, ssl, FALSE);
}
HTTPResponse SendPost(const char *url, const char *urlpath, const char *headers, const char *body, BOOL ssl) {
return SendHttpRequest(url, urlpath, body, headers, ssl, TRUE);
}