A Fully Featured Windows HTTP Wrapper in C++

It is also posted at CodeProject.com (Here).

Download Source

Introduction

This is a fully featured Windows HTTP Wrapper in C++. It is wrapper in C++ class. It is fully featured and easy to use. You only need to include one single header file to use the wrapper.

Background

Several months ago, I posted my first article A Simple Windows HTTP Wrapper Using C++ in CodeProject, I continued to update it in the last several months and finally got the fully featured Windows HTTP Wrapper based on WinHTTP APIs in C++.

Features

  • Cookies supported
  • Proxy supported
  • GET, POST method supported
  • Request headers customization supported
  • Disable automatic redirection supported
  • https supported
  • Receive progress supported
  • Some other features

Using the code

The class diagram is as follows.

You can understand most of the functions from their names. Please refer to the examples section for some typical examples.

Examples

Simple Get Request

Get request is the most common requests. Browsing a web page causes one or several Get requests.

    // Set URL.
    WinHttpClient client(L"http://www.codeproject.com/");

    // Send http request, a GET request by default.
    client.SendHttpRequest();

    // The response header.
    wstring httpResponseHeader = client.GetResponseHeader();

    // The response content.
    wstring httpResponseContent = client.GetResponseContent();

Simple Post request

Post request usually occurs while logging in or posting a thread.

    WinHttpClient client(L"http://www.codeproject.com/");

    // Set post data.
    string data = "title=A_NEW_THREAD&content=This_is_a_new_thread.";
    client.SetAdditionalDataToSend((BYTE *)data.c_str(), data.size());

    // Set request headers.
    wchar_t szSize[50] = L"";
    swprintf_s(szSize, L"%d", data.size());
    wstring headers = L"Content-Length: ";
    headers += szSize;
    headers += L"\r\nContent-Type: application/x-www-form-urlencoded\r\n";
    client.SetAdditionalRequestHeaders(headers);

    // Send http post request.
    client.SendHttpRequest(L"POST");

    wstring httpResponseHeader = client.GetResponseHeader();
    wstring httpResponseContent = client.GetResponseContent();

Getting Request’s Progress

You can specify a call back function to get the request’s progress.

// Progress - finished percentage.
bool ProgressProc(double progress)
{
    wprintf(L"Current progress: %-.1f%%\r\n", progress);
    return true;
}

void ProgressTest(void)
{
    // Set URL and call back function.
    WinHttpClient client(L"http://www.codeproject.com/", ProgressProc);
    client.SendHttpRequest();
    wstring httpResponseHeader = client.GetResponseHeader();
    wstring httpResponseContent = client.GetResponseContent();
}

Specifying the User Agent

User agent is a string used by the clients to identify themselves to the web server so that the server can tell which client software you use, IE8, Chrome or FireFox. You can specify the user agent to pretend to be IE8 to fool the web server because sometime server only supports IE8.

    WinHttpClient client(L"http://www.codeproject.com/");

    // Set the user agent to the same as IE8.
    client.SetUserAgent(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1;...)");

    client.SendHttpRequest();
    wstring httpResponseHeader = client.GetResponseHeader();
    wstring httpResponseContent = client.GetResponseContent();

Specifying the Proxy

Sometimes we have to connect to the web through proxies. WinHttpClient connects to the web server directly and then uses the IE setting to connect if fail by default. You can also specify the proxy by calling function SetProxy.

    WinHttpClient client(L"http://www.codeproject.com/");

    // Set the proxy to 192.168.0.1 with port 8080.
    client.SetProxy(L"192.168.0.1:8080");

    client.SendHttpRequest();
    wstring httpResponseHeader = client.GetResponseHeader();
    wstring httpResponseContent = client.GetResponseContent();

Handling Cookies

A cookie (also tracking cookie, browser cookie, and HTTP cookie) is a small piece of text stored on a user’s computer by a web browser. A cookie consists of one or more name-value pairs containing bits of information.

The cookie is sent as an HTTP header by a web server to a web browser and then sent back unchanged by the browser each time it accesses that server. A cookie can be used for authentication, session tracking (state maintenance), storing site preferences, shopping cart contents, the identifier for a server-based session, or anything else that can be accomplished through storing textual data. (http://en.wikipedia.org/wiki/HTTP_cookie)

You can specify cookies to send by calling SetAdditionalRequestCookies and get the response cookies by calling GetResponseCookies.

    WinHttpClient client(L"http://www.codeproject.com/");

    // Set the cookies to send.
    client.SetAdditionalRequestCookies(L"username=jack");

    client.SendHttpRequest();

    // Get the response cookies.
    wstring httpResponseCookies = client.GetResponseCookies();

    wstring httpResponseHeader = client.GetResponseHeader();
    wstring httpResponseContent = client.GetResponseContent();

A Complete Example

Codeproject.com needs logging in to download the files. This example logs in, gets the cookies, requests the source code (http://www.codeproject.com/KB/IP/win_HTTP_wrapper/WinHttpClient_Src.zip) of my first Codeproject article A Simple Windows HTTP Wrapper Using C++ and then saves the file to hard disk. This example includes cookies handling, post requests, request headers customization, etc.

    // 1. Get the initial cookie.
    WinHttpClient getClient(L"http://www.codeproject.com/script/Membership/LogOn.aspx");
    getClient.SetAdditionalRequestHeaders(L"Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, ...");
    if (!getClient.SendHttpRequest())
    {
        return;
    }

    // 2. Post data to get the authentication cookie.
    WinHttpClient postClient(L"http://www.codeproject.com/script/Membership/LogOn.aspx");

    // Post data.
    wstring username = L"YourCodeProjectUsername";
    wstring password = L"YourPassword";
    postClient.SetAdditionalRequestCookies(getClient.GetResponseCookies());
    string data = "FormName=MenuBarForm&Email=";
    data += (char *)_bstr_t(username.c_str());
    data += "&Password=";
    data += (char *)_bstr_t(password.c_str());
    data += "&RememberMeCheck=1";
    postClient.SetAdditionalDataToSend((BYTE *)data.c_str(), data.size());

    // Post headers.
    wstring headers = L"...Content-Length: %d\r\nProxy-Connection: Keep-Alive\r\nPragma: no-cache\r\n";
    wchar_t szHeaders[MAX_PATH * 10] = L"";
    swprintf_s(szHeaders, MAX_PATH * 10, headers.c_str(), data.size());
    postClient.SetAdditionalRequestHeaders(szHeaders);
    if (!postClient.SendHttpRequest(L"POST", true))
    {
        return;
    }

    // 3. Finally get the zip file.
    WinHttpClient downloadClient(L"http://www.codeproject.com/KB/IP/win_HTTP_wrapper/WinHttpClient_Src.zip");
    downloadClient.SetUserAgent(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; ...)");

    // Sending this cookie make server believe you have already logged in.
    downloadClient.SetAdditionalRequestCookies(postClient.GetResponseCookies());
    if (!downloadClient.SendHttpRequest())
    {
        return;
    }
    downloadClient.SaveResponseToFile(L"C:\\WinHttpClient_Src.zip");

Points of Interest

  • Sometimes it is a good idea to get a piece of new code work first and improve it later.
  • Read the Hypertext Transfer Protocol (RFC 2616) will help a lot.
  • Use HTTP monitoring tools to help the developments. Such as HTTPAnalyzer or HTTPWatch.
  • It is fast and easy to use class _bstr_t to convert between wchar_t* and char*.

History

2009-9 fully featured version.

2008-7 initial version.

One thought on “A Fully Featured Windows HTTP Wrapper in C++

Comments are closed.