Last active
June 10, 2018 12:53
-
-
Save henkman/db26187c8ccf306f7e06ca5f7fcc7d12 to your computer and use it in GitHub Desktop.
single header C api for http request
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typedef struct | |
{ | |
size_t size, cap; | |
char *data; | |
} Buffer; | |
static size_t next_power_of_two(size_t v) | |
{ | |
v--; | |
v |= v >> 1; | |
v |= v >> 2; | |
v |= v >> 4; | |
v |= v >> 8; | |
v |= v >> 16; | |
v++; | |
return v; | |
} | |
static void buffer_init(Buffer *b, size_t initial) | |
{ | |
b->size = 0; | |
b->cap = initial; | |
b->data = malloc(sizeof(char) * initial); | |
} | |
static void buffer_grow(Buffer *b, size_t size) | |
{ | |
size_t n = b->size + size; | |
if (n >= b->cap) | |
{ | |
b->cap = next_power_of_two(n); | |
b->data = realloc(b->data, b->cap); | |
} | |
} | |
static void buffer_write(Buffer *b, char *data, size_t size) | |
{ | |
buffer_grow(b, size); | |
memcpy(&b->data[b->size], data, size); | |
b->size += size; | |
} | |
static void buffer_reset(Buffer *b) | |
{ | |
b->size = 0; | |
} | |
static void buffer_free(Buffer *b) | |
{ | |
free(b->data); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef _WIN32 | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
#include <winhttp.h> | |
static int http(wchar_t *method, wchar_t *host, short port, wchar_t *path, | |
wchar_t *headers, unsigned char *data, size_t size, | |
Buffer *response) | |
{ | |
int code = 0; | |
HINTERNET hConnect = NULL, hRequest = NULL; | |
HINTERNET hSession = WinHttpOpen(NULL, | |
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, | |
WINHTTP_NO_PROXY_NAME, | |
WINHTTP_NO_PROXY_BYPASS, 0); | |
if (!hSession) | |
{ | |
code = 1; | |
goto end; | |
} | |
hConnect = WinHttpConnect(hSession, host, port, 0); | |
if (!hConnect) | |
{ | |
code = 2; | |
goto end; | |
} | |
hRequest = WinHttpOpenRequest(hConnect, method, path, | |
NULL, WINHTTP_NO_REFERER, | |
WINHTTP_DEFAULT_ACCEPT_TYPES, | |
WINHTTP_FLAG_SECURE); | |
if (!hRequest) | |
{ | |
code = 3; | |
goto end; | |
} | |
DWORD dwFlags = | |
SECURITY_FLAG_IGNORE_UNKNOWN_CA | | |
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE | | |
SECURITY_FLAG_IGNORE_CERT_CN_INVALID | | |
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID; | |
if (!WinHttpSetOption( | |
hRequest, | |
WINHTTP_OPTION_SECURITY_FLAGS, | |
&dwFlags, | |
sizeof(dwFlags))) | |
{ | |
code = 4; | |
goto end; | |
} | |
if (!WinHttpSendRequest(hRequest, headers, headers != NULL ? -1L : 0, | |
WINHTTP_NO_REQUEST_DATA, 0, | |
size, 0)) | |
{ | |
code = 5; | |
goto end; | |
} | |
if (size > 0) | |
{ | |
DWORD dwBytesWritten; | |
if (!WinHttpWriteData(hRequest, data, size, &dwBytesWritten)) | |
{ | |
code = 6; | |
goto end; | |
} | |
} | |
if (!WinHttpReceiveResponse(hRequest, NULL)) | |
{ | |
code = 7; | |
goto end; | |
} | |
if (response != NULL) | |
{ | |
DWORD dwDownloaded, dwSize; | |
do | |
{ | |
if (!WinHttpQueryDataAvailable(hRequest, &dwSize) && dwSize) | |
break; | |
buffer_growby(response, dwSize); | |
WinHttpReadData(hRequest, (LPVOID)&response->data[response->size], dwSize, &dwDownloaded); | |
response->size += dwSize; | |
if (!dwDownloaded) | |
break; | |
} while (dwSize > 0); | |
} | |
end: | |
if (hRequest) | |
WinHttpCloseHandle(hRequest); | |
if (hConnect) | |
WinHttpCloseHandle(hConnect); | |
if (hSession) | |
WinHttpCloseHandle(hSession); | |
return code; | |
} | |
#else | |
#error "not supported" | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment