Click here to Skip to main content
15,867,453 members
Articles / Mobile Apps / Windows Mobile

An Asynchronous HTTP Request WinINet Wrapper in C++

Rate me:
Please Sign up or sign in to vote.
4.90/5 (45 votes)
25 Aug 2011CPOL2 min read 133.6K   8.8K   172   27
An asynchronous HTTP download class for C++
Image 1

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.
    C++
    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:

C++
// 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:

C++
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

C++
// 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

C++
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

C++
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:

C++
#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:

C++
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.

C++
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

C++
// 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

C++
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)


Written By
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

 
QuestionNot multiplatform Pin
Jaime Stuardo - Chile12-Apr-17 8:11
Jaime Stuardo - Chile12-Apr-17 8:11 
QuestionVery Good Pin
DeanV10-Oct-16 7:40
DeanV10-Oct-16 7:40 
GeneralMy vote of 5 Pin
MaitreyaBuddha16-May-15 0:58
MaitreyaBuddha16-May-15 0:58 
GeneralAwesome Asynch and event-driven HTTP class! Pin
MaitreyaBuddha16-May-15 0:57
MaitreyaBuddha16-May-15 0:57 
QuestionReally nice Pin
Jonathan Potter11-Mar-15 20:32
Jonathan Potter11-Mar-15 20:32 
QuestionSetProcessWorkingSetSize Pin
anandssunku6-Jul-14 20:04
anandssunku6-Jul-14 20:04 
QuestionSource code Pin
Michael Haephrati20-Feb-13 7:49
professionalMichael Haephrati20-Feb-13 7:49 
GeneralMy vote of 5 Pin
Michael Haephrati20-Feb-13 7:45
professionalMichael Haephrati20-Feb-13 7:45 
QuestionAfter update... how make this synchronous?? Pin
mrgalwen30-Aug-12 6:37
mrgalwen30-Aug-12 6:37 
AnswerRe: After update... how make this synchronous?? Pin
crazybit4-Sep-12 21:26
crazybit4-Sep-12 21:26 
Generalvery nice! Pin
liuchuan29014-Jun-12 22:18
liuchuan29014-Jun-12 22:18 
GeneralMy vote of 5 Pin
ZzwKathleen4-Jun-12 16:03
ZzwKathleen4-Jun-12 16:03 
Question居然又碰到了,呵呵 Pin
shengcheng_jin29-Aug-11 23:50
shengcheng_jin29-Aug-11 23:50 
AnswerRe: 居然又碰到了,呵呵 Pin
crazybit30-Aug-11 0:23
crazybit30-Aug-11 0:23 
GeneralLast example not working Pin
KL@DotNet4-Jan-10 1:37
KL@DotNet4-Jan-10 1:37 
GeneralRe: Last example not working Pin
KL@DotNet4-Jan-10 4:32
KL@DotNet4-Jan-10 4:32 
GeneralRe: Last example not working Pin
crazybit4-Jan-10 17:58
crazybit4-Jan-10 17:58 
QuestionMake the code synchronous ? Pin
darthmaul30-Dec-09 7:53
darthmaul30-Dec-09 7:53 
AnswerRe: Make the code synchronous ? Pin
crazybit4-Jan-10 17:50
crazybit4-Jan-10 17:50 
GeneralRe: Make the code synchronous ? Pin
darthmaul4-Jan-10 22:32
darthmaul4-Jan-10 22:32 
QuestionSupport for https ? Pin
irol19-Nov-09 23:54
professionalirol19-Nov-09 23:54 
AnswerRe: Support for https ? Pin
crazybit23-Nov-09 2:55
crazybit23-Nov-09 2:55 
QuestionSupport pause and resume functions? Pin
Symfund18-Nov-09 14:13
Symfund18-Nov-09 14:13 
AnswerRe: Support pause and resume functions? Pin
crazybit18-Nov-09 15:07
crazybit18-Nov-09 15:07 
AnswerRe: Support pause and resume functions? Pin
Anton Afanasyev30-Jan-10 14:33
Anton Afanasyev30-Jan-10 14:33 

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

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