Sending HTTP Requests
This document details how to programmatically send HTTP requests from a Windows application. Understanding the fundamental components of HTTP communication is crucial for developing robust network-enabled applications.
Introduction to HTTP Client Programming
HTTP (Hypertext Transfer Protocol) is the foundation of data communication on the World Wide Web. As a Windows developer, you can leverage various APIs to send HTTP requests to web servers, retrieve resources, and interact with web services.
Core Concepts
- Request Methods: GET, POST, PUT, DELETE, HEAD, OPTIONS, etc.
- Headers: Metadata about the request or response (e.g.,
Content-Type,User-Agent). - Body: The actual data being sent (e.g., form data, JSON payloads).
- Status Codes: Indicate the result of the request (e.g., 200 OK, 404 Not Found, 500 Internal Server Error).
Using WinHTTP
WinHTTP is a Windows API that provides a high-level interface for sending HTTP requests. It's recommended for most client-side HTTP development due to its robustness and support for modern HTTP features.
Basic GET Request Example
Here's a C++ example demonstrating a simple GET request using WinHTTP:
#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
void SendHttpGetRequest(const wchar_t* serverName, const wchar_t* urlPath) {
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
wchar_t buffer[1024];
DWORD bytesRead;
// Initialize WinHTTP
hSession = WinHttpOpen( L"MyWinHTTPClient/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_VISTA,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0 );
if (!hSession) {
// Handle error
return;
}
// Connect to the HTTP server
hConnect = WinHttpConnect( hSession, serverName, INTERNET_DEFAULT_HTTP_PORT, 0 );
if (!hConnect) {
// Handle error
WinHttpCloseHandle(hSession);
return;
}
// Open an HTTP request handle
hRequest = WinHttpOpenRequest( hConnect,
L"GET",
urlPath,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0 );
if (!hRequest) {
// Handle error
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return;
}
// Send the request
if (!WinHttpSendRequest( hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0 )) {
// Handle error
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return;
}
// Receive the response
if (!WinHttpReceiveResponse( hRequest, NULL )) {
// Handle error
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return;
}
// Read the response headers
DWORD dwSize = sizeof(buffer);
if (!WinHttpQueryHeaders( hRequest,
WINHTTP_HEADERS_DIRECT | WINHTTP_QUERY_RAW_HEADERS,
WINHTTP_HEADER_NAME_BY_POSITION,
buffer,
&dwSize,
WINHTTP_HEADER_END )) {
// Handle error
} else {
wprintf(L"Response Headers:\n%s\n", buffer);
}
// Read the response body
do {
bytesRead = 0;
if (!WinHttpReadData( hRequest,
(LPVOID)buffer,
sizeof(buffer) - 1,
&bytesRead )) {
// Handle error
break;
}
buffer[bytesRead / sizeof(buffer[0])] = '\0';
wprintf(L"%s", buffer);
} while (bytesRead > 0);
// Clean up
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
}
int main() {
SendHttpGetRequest(L"www.example.com", L"/");
return 0;
}
Using WinINet
WinINet is another older API for handling Internet protocols, including HTTP. While still supported, WinHTTP is generally preferred for new development.
Sending POST Requests
To send a POST request, you'll need to specify the "POST" method in WinHttpOpenRequest and provide data in the request body using WinHttpWriteData. You should also set the Content-Type header appropriately.
GetLastError() to retrieve specific error codes.
Asynchronous Operations
For applications that require a responsive user interface, consider using asynchronous operations with WinHTTP. This prevents blocking the UI thread while waiting for network responses.