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

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.

Note: Always ensure you handle potential errors at each API call. Check the return values of WinHTTP functions and use 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.

Further Reading