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;
}