WinHTTP API Reference
The WinHTTP API provides a high-level interface for Windows-based applications to access HTTP resources. It is designed for server-side applications and complex client applications that require more control over HTTP communication than the WinINet API offers. This reference details the functions, structures, constants, and return values that comprise the WinHTTP API.
Overview
WinHTTP is a set of Win32 APIs that enable applications to send HTTP requests to any origin server and receive responses. It is well-suited for applications that require robust HTTP functionality, including:
- Server applications acting as HTTP clients.
- Applications requiring advanced control over HTTP headers, proxy settings, and authentication.
- Applications that need to manage multiple concurrent HTTP connections efficiently.
WinHTTP handles many aspects of HTTP communication, such as connection management, request framing, and response parsing, allowing developers to focus on the application logic.
Key Concepts
- Sessions: A WinHTTP session object represents a connection to an HTTP server.
- Connections: A connection object represents a single HTTP request to a server.
- Requests: The actual HTTP request being sent to the server, including method, URL, headers, and body.
- Responses: The data received from the server, including status codes, headers, and body.
Understanding these concepts is crucial for effective use of the WinHTTP API.
Core Functions
The WinHTTP API exposes a variety of functions for managing HTTP sessions, requests, and responses. Here are some of the most commonly used functions:
Session Management
WinHttpOpen
Initializes a WinHTTP session. This is the first WinHTTP function that an application typically calls.
HINTERNET WinHttpOpen(
LPCWSTR pszAgentW,
DWORD dwAccessType,
LPCWSTR pszProxyNameW,
LPCWSTR pszProxyBypassW,
DWORD dwFlags
);
WinHttpCloseHandle
Closes a WinHTTP handle (session, connection, or request).
BOOL WinHttpCloseHandle(
HINTERNET hInternet
);
Request Management
WinHttpOpenRequest
Creates an HTTP request handle. This function specifies the HTTP method, URL, and version.
HINTERNET WinHttpOpenRequest(
HINTERNET hConnect,
LPCWSTR pwszMethod,
LPCWSTR pwszUrl,
LPCWSTR pwszVersion,
LPCWSTR pwszReferer,
LPCWSTR *ppwszAcceptTypes,
DWORD dwFlags
);
WinHttpSendRequest
Sends the specified HTTP request to the server. Can optionally send request headers and data.
BOOL WinHttpSendRequest(
HINTERNET hRequest,
LPCWSTR pwszHeaders,
DWORD dwHeadersLength,
LPVOID lpOptional,
DWORD dwOptionalLength,
DWORD dwTotalLength,
DWORD_PTR pdwContext
);
WinHttpReceiveResponse
Waits for the server to send a response to the request specified by the hRequest handle.
BOOL WinHttpReceiveResponse(
HINTERNET hRequest,
LPDWORD lpdwNumberOfBytesAvailable
);
WinHttpReadData
Reads data from the HTTP response body.
BOOL WinHttpReadData(
HINTERNET hRequest,
LPVOID lpBuffer,
DWORD dwNumberOfBytesToRead,
LPDWORD lpdwNumberOfBytesRead
);
Error Handling
Error handling is critical. WinHTTP functions return a non-zero value on success and zero on failure. To get more detailed error information, use WinHttpGetLastError and WinHttpQueryOption with WINHTTP_OPTION_LAST_ERROR.
WinHttpGetLastError
Retrieves the last error code associated with WinHTTP.
DWORD WinHttpGetLastError();
Example: Simple GET Request
This example demonstrates a basic GET request using WinHTTP.
#include <windows.h>
#include <winhttp.h>
#include <stdio.h>
#pragma comment(lib, "winhttp.lib")
int main() {
HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL;
LPVOID buffer = NULL;
DWORD bytesRead = 0;
DWORD statusCode = 0;
DWORD dwSize = sizeof(statusCode);
BOOL result = FALSE;
// 1. Initialize WinHTTP
hSession = WinHttpOpen(L"MyApp/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (!hSession) {
fprintf(stderr, "WinHttpOpen failed: %u\n", GetLastError());
goto cleanup;
}
// 2. Open a connection to the server
hConnect = WinHttpConnect(hSession, L"www.example.com", INTERNET_DEFAULT_HTTP_PORT, 0);
if (!hConnect) {
fprintf(stderr, "WinHttpConnect failed: %u\n", GetLastError());
goto cleanup;
}
// 3. Open an HTTP request
hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
if (!hRequest) {
fprintf(stderr, "WinHttpOpenRequest failed: %u\n", GetLastError());
goto cleanup;
}
// 4. Send the request
result = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
if (!result) {
fprintf(stderr, "WinHttpSendRequest failed: %u\n", GetLastError());
goto cleanup;
}
// 5. Receive the response
result = WinHttpReceiveResponse(hRequest, NULL);
if (!result) {
fprintf(stderr, "WinHttpReceiveResponse failed: %u\n", GetLastError());
goto cleanup;
}
// Optional: Get the status code
if (WinHttpQueryOption(hRequest, WINHTTP_OPTION_HTTP_STATUS_CODE, &statusCode, &dwSize)) {
printf("HTTP Status Code: %lu\n", statusCode);
}
// 6. Read the response body
// Determine the size of the response body first
DWORD dwContentLength = 0;
DWORD dwSizeContentLength = sizeof(dwContentLength);
if (WinHttpQueryHeaders(hRequest, WINHTTP_HEADERS_OPTIONS_CONTENT_LENGTH, WINHTTP_NO_HEADER_NAME, &dwContentLength, &dwSizeContentLength, NULL)) {
buffer = malloc(dwContentLength + 1); // +1 for null terminator
if (buffer) {
result = WinHttpReadData(hRequest, buffer, dwContentLength, &bytesRead);
if (result && bytesRead == dwContentLength) {
((char*)buffer)[bytesRead] = '\0'; // Null-terminate the buffer
printf("Response Body:\n%s\n", (char*)buffer);
} else {
fprintf(stderr, "WinHttpReadData failed or did not read all bytes: %u\n", GetLastError());
}
} else {
fprintf(stderr, "Memory allocation failed.\n");
}
} else {
fprintf(stderr, "Failed to get Content-Length: %u\n", GetLastError());
}
cleanup:
// 7. Clean up
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
if (buffer) free(buffer);
return 0;
}