Click here to Skip to main content
Click here to Skip to main content

An Asynchronous HTTP Request WinINet Wrapper in C++

, 25 Aug 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
An asynchronous HTTP download class for C++

Introduction

WinINet makes network programming easier, but it's difficult to use for C++ because of its C-style interface, so I write this code to wrap it. Using it, you can easily create an asynchronous HTTP request and receive event callback. It can be applied to MFC and ATL projects.

This code mainly consists of two classes: class FCHttpRequest and class FCHttpRequestManager.

Class FCHttpRequest is responsible for implementing send HTTP request and receive response, it's a wrapper class for WinINet.

Class FCHttpRequestManager is a management of FCHttpRequest, responsible for add, delete FCHttpRequest object and receive event from FCHttpRequest.

Similar to the STL and Boost, all source code consists of .h and .inl file, you can easily integrate it into your program.

How to Use

  1. Include http_request_manager.h file in your project. normally include it at the end of the stdafx.h.
  2. Create HTTP request manager class derived from class FCHttpRequestManager.
    class CMyManager : public FCHttpRequestManager
    {
        //...
    };
    
    // multiple inheritance attach an exist class
    class CMyManager : public CDialog,
                       public FCHttpRequestManager
    {
        virtual void OnAfterRequestSend (FCHttpRequest& rTask)
        {
            // ...
        }
    
        virtual void OnAfterRequestFinish (FCHttpRequest& rTask)
        {
            // ...
        }
    };

    The manager will receive two events: OnAfterRequestSend and OnAfterRequestFinish, overwrite event you find interesting. Most of the time, we should overwrite OnAfterRequestFinish to process received data.

  3. Now, you can send HTTP request by calling AddRequest.

Examples

... Download File

Send HTTP request:

// download whole file
AddDownload (_T("http://phoxo.com/t.zip")) ;

// download file and specifies the starting position
HTTP_REQUEST_HEADER   h ;
h.m_url = _T("http://phoxo.com/t.zip") ;
h.m_start = 30 ; // in byte
AddRequest (h) ;

Response finish event, process downloaded data:

void OnAfterRequestFinish (FCHttpRequest& rTask)
{
    const HTTP_RESPONSE_INFO   & r = rTask.GetResponseInfo() ;

    bool   bOK = false ;
    if (r.m_status_code == HTTP_STATUS_OK)
    {
        if (r.m_content_length)
        {
            // avoid network broken during downloading
            if (r.m_content_length == rTask.GetTotalReceiveByte())
                bOK = true ;
        }
        else
        {
            // no Content-Type field, maybe is a dynamic page, such as PHP, ASP...
            if (r.m_final_read_result)
                bOK = true ;
        }
    }

    if (bOK)
    {
        std::string   receive_data ;
        rTask.PopReceived (receive_data) ;

        // ... process received data
    }
}

... Specifying the User-Agent

// default User-Agent is same to User-Agent of IE
HTTP_REQUEST_HEADER   h ;
h.m_url = _T("http://phoxo.com/") ;
h.m_user_agent = _T("My User-Agent") ;
AddRequest (h) ;

... Custom HTTP Header

HTTP_REQUEST_HEADER   h ;
h.m_url = _T("http://phoxo.com/") ;

// \r\n at end of each line
h.m_header += _T("Referer: http://google.com\r\n") ;
h.m_header += _T("Accept: */*\r\n") ;
h.m_header += _T("x-flash-version: 10,0,0,1\r\n") ;

AddRequest (h) ;

... Specifying the Proxy

HTTP_REQUEST_HEADER   h ;
h.m_url = _T("http://phoxo.com/") ;
h.m_proxy_ip = _T("8.8.8.8") ;
h.m_proxy_port = 8080 ;
AddRequest (h) ;

... Decompress GZip HTTP Data

This feature requires the ZLib library, you can get it from http://www.zlib.org.
Include headers in the following order:

#include "zlib.h"
#include "http_request_manager.h"
#include "utility/gzip_decompress.h"

Add Accept-Encoding field in request header, notify the server that you can accept gzip compressed data:

HTTP_REQUEST_HEADER   h ;
h.m_url = _T("http://phoxo.com/") ;
h.m_header += L"Accept-Encoding: gzip, deflate\r\n" ;
AddRequest (h) ;

In finish callback, you can use gzip_decompress to decompress received data.

void OnAfterRequestFinish (FCHttpRequest& rTask)
{
    std::string   receive_data ;
    rTask.PopReceived (receive_data) ;

    if (IsReceiveGZipStream(rTask) && receive_data.size())
    {
        std::string   raw_data ;
        if (gzip_decompress (receive_data.c_str(), receive_data.size(), raw_data))
        {
            receive_data = raw_data ;
        }
    }
}

... Post multipart/form-data

// this example loads image to memory, then posts to server using multipart/form-data
std::vector<byte />   buf ;
FCFileEx::Read (_T("c:\\1.jpg"), buf) ;

HTTP_REQUEST_HEADER   h (HTTP_REQUEST_HEADER::VERB_TYPE_POST_MULTIPART) ;
h.m_url = _T("http://phoxo.com/") ;
h.AddMultipartFormData ("param1", "value1") ;
h.AddMultipartFormData ("param2", "value2") ;
h.AddMultipartFormData ("pic", &buf[0], buf.size(), "1.jpg") ;
h.EndMultipartFormData() ;
m_task_id = AddRequest (h) ;

... HTTPS

HTTP_REQUEST_HEADER   h ;
h.m_url = _T("https://phoxo.com/") ;

// ignores errors that can be caused by the certificate 
// host name of the server not matching the host name in the request
h.m_open_flag |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID ;

// ignores errors that can be caused by an expired server certificate
h.m_open_flag |= INTERNET_FLAG_IGNORE_CERT_DATE_INVALID ;

AddRequest (h) ;

History

  • 25th August, 2011: V2.0
    • Refactoring code, more features, more efficient
    • Added multipart/form-data POST support
    • Added HTTPS support
    • Added GZip decompress support
  • 30th January, 2010: V1.1
    • Renamed from FCHttpDownloadExec to FCHttpDownload
    • Fixed a bug when popping a modal dialog in callback
    • Modified interface of FCHttpRequestManager
    • Got default User-Agent from Internet Explorer
  • 17th November, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

crazybit
Team Leader PhoXo
China China
graduate from University of Science and Technology of China at 2002.
 
Now I work at www.phoxo.com.

Comments and Discussions

 
QuestionSetProcessWorkingSetSize Pinmemberanandssunku6-Jul-14 20:04 
QuestionSource code PinmvpMichael Haephrati מיכאל האפרתי20-Feb-13 7:49 
GeneralMy vote of 5 PinmvpMichael Haephrati מיכאל האפרתי20-Feb-13 7:45 
Great
QuestionAfter update... how make this synchronous?? Pinmembermrgalwen30-Aug-12 6:37 
AnswerRe: After update... how make this synchronous?? Pinmembercrazybit4-Sep-12 21:26 
Generalvery nice! Pinmemberliuchuan29014-Jun-12 22:18 
GeneralMy vote of 5 PinmemberZzwKathleen4-Jun-12 16:03 
Question居然又碰到了,呵呵 Pinmembershengcheng_jin29-Aug-11 23:50 
AnswerRe: 居然又碰到了,呵呵 Pinmembercrazybit30-Aug-11 0:23 
GeneralLast example not working PinmemberKL@DotNet4-Jan-10 1:37 
GeneralRe: Last example not working PinmemberKL@DotNet4-Jan-10 4:32 
GeneralRe: Last example not working Pinmembercrazybit4-Jan-10 17:58 
QuestionMake the code synchronous ? Pinmemberdarthmaul30-Dec-09 7:53 
AnswerRe: Make the code synchronous ? Pinmembercrazybit4-Jan-10 17:50 
GeneralRe: Make the code synchronous ? Pinmemberdarthmaul4-Jan-10 22:32 
QuestionSupport for https ? Pinmemberirol19-Nov-09 23:54 
AnswerRe: Support for https ? Pinmembercrazybit23-Nov-09 2:55 
QuestionSupport pause and resume functions? PingroupSymfund18-Nov-09 14:13 
AnswerRe: Support pause and resume functions? Pinmembercrazybit18-Nov-09 15:07 
AnswerRe: Support pause and resume functions? PinmemberAnton Afanasyev30-Jan-10 14:33 
Generalbatch download Pinmembertransoft18-Nov-09 2:41 
GeneralRe: batch download Pinmembercrazybit18-Nov-09 4:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141030.1 | Last Updated 25 Aug 2011
Article Copyright 2009 by crazybit
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid