Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Use Curl to Organise Your HTTP Request

4.91/5 (10 votes)
25 Nov 2015CPOL4 min read 25.3K  
How to perform easy http request

Introduction

Under Windows platform, organize an HTTP request with C++ code may cost plenty of time. This article will introduce curl to you to solve this problem.

Background

CURL is an opensource lib under Windows which is used to send and receive http packages. We can easily complete http tasks with lib curl.

Using the Code

This tip may not provide a completed project or source code for you to compile and run. I will introduce how to use the libcurl with C++ project. I will list some key codes at the same time.

1. Getting Started with Lib CURL

1.1 Download CURL & Compile

We can get the latest version of CURL at http://curl.haxx.se/download.html. The latest version I use is the 7.45.0.I get the source code package for Windows: curl-7.45.0.zip.

After you finished downloading, unzip the package at E:\ThirdPartyLib\curl-7.45.0. We can find the VS project file under the path: E:\ThirdPartyLib\curl-7.45.0\projects\Windows. Open the project file with Visual Studio and compile the source code as a lib or DLL.

When you compile the source code, you may get some errors that can't find the openssl or libssh2. You can get the openssl at http://www.openssl.org/source/. libssh can be downloaded through your search engine.

P.S.: Compile the opensll may need the ActivePerl.

1.2 Insert the CURL into Your Project

If you successfully compiled the source code, you will get the libcurld.lib for debug or libcurl.lib for release. Just copy this lib to your project library directory and include this lib.

2. Synchronous and Asynchronous Operation in CURL

When send http request to the server, there will two different kinds of conditions.

2.1 You send some simple request such as update a parameter's value

This kind of request usually needs immediate reply.The CURL provides the synchoronous method curl_easy_perform to handle this.

2.2 You want to download from server through your request

This kind of request may cost some time for the server to operate. So we can't get a reply right now. The asynchronous method curl_multi_init can apply a multi-thread space to run this kind of request. If you want to add a request to the multi-thread space, use the curl_multi_add_handle. curl_multi_perform is used to make the multi-thread space begin to run, but you need to call this method continuously to motivate the multi-thread space if there are any requests that are not finished.

3. Pack your HTTP Request Up

I will display a POST example to show how to pack http request with CURL.

C++
CURL* pHandle =curl_easy_init();
curl_easy_setopt(pHandle,CURLOPT_URL,Url);
curl_easy_setopt(pHandle,CURLOPT_TIMEOUT,timeout);
curl_easy_setopt(pHandle,CURLOPT_POST,1L);

The code above completes a simple http request head which only includes the request address, timeout and http type:POST.

Then, we should add the request body which shows what you want the server to do to the request. If your request doesn't contain any enclosure, we just need to set the Postfields:

C++
curl_easy_setopt(pHandle,CURLOPT_POSTFIELDS,requesuList);

The requestList is the url-encode: a list of key=value string split with the ‘&‘. For example: "Name=test&Password=123&Type = 1"

After these steps, a simple http post request is packed up. Call curl_easy_perform to run.

If our request contains an enclosure, we should change the packing up method.

C++
CURL* pHandle =curl_easy_init();
curl_easy_setopt(pHandle,CURLOPT_URL,Url);
curl_easy_setopt(pHandle,CURLOPT_TIMEOUT,timeout);

The header seems to be the same, but the posttype doesn't need to be set. Because of the enclosure, we should use the multi-part to organize the http package. The postfields above should be post in multi-part too.

C++
struct curl_httppost *formpost=NULL;
struct curl_httppost *lastptr=NULL;
curl_formadd(&formpost,
             &lastptr,
             CURLFORM_COPYNAME, Key,
             CURLFORM_COPYCONTENTS, Value,
             CURLFORM_END);

The key and value represent the "key = value" pair in the postfields. If there is more than one pair, you can call a loop to add like the example above.

Then, we will add the file information:

C++
curl_formadd(&formpost,
             &lastptr,
             CURLFORM_COPYNAME, "filename",
             CURLFORM_COPYCONTENTS, FileName,
             CURLFORM_END);
curl_formadd(&formpost,
             &lastptr,
             CURLFORM_COPYNAME, "size",
             CURLFORM_COPYCONTENTS, FileSize,
             CURLFORM_END);
curl_formadd(&formpost,
             &lastptr,
             CURLFORM_COPYNAME, "fileContent",
             CURLFORM_FILE, filepath,
             CURLFORM_END);

The form is the same with the example above. If you don't know what CURLFORM_COPYNAME to insert, you should ask your server.

If there is more than one file, call loop to insert.

After you finish the multi-part form, we should add this form to the CURL handle:

C++
curl_easy_setopt(pHandle,CURLOPT_HTTPPOST,formpost);

Till now, a basic CURL based http request is packed up. But there comes a problem: How to get the upload progress?

The CURL provides many options for the developer to set to monitor the status of the http request:

C++
curl_easy_setopt(pHandle,CURLOPT_NOPROGRESS,0L);
curl_easy_setopt(pHandle,CURLOPT_PROGRESSFUNCTION,getProgress);
curl_easy_setopt(pHandle,CURLOPT_PROGRESSDATA,data);

These three codes open the progress switch. Set the call back function getprogress and the data send to the callback: data. You can find the function definition of the getProgress in the header files.

At the same time, if your request is downloading file, you may need to set the WRITEDATA options:

C++
curl_easy_setopt(pHandle, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(pHandle, CURLOPT_WRITEDATA, data);

Now, the request is finished.

4.Get the http request Execute Result

If you call the curl_easy_perform, your request will be executed immediately.

C++
curl_easy_getinfo(pHandle,CURLINFO_HTTP_CODE,&HttpReturnCode);

curl_easy_getinfo can give you many returned status of the request.

If you call the curl_multi_perform, your request may be executed later. These codes show how to manage the running status of the request:

C++
do{
     curl_multi_perform(m_phttpQuestList, &RunningNum);
     URLMcode mc; 
     int numfds;

     /* wait for activity, timeout or "nothing" */
     mc = curl_multi_wait(m_phttpQuestList, NULL, 0, 1000, &numfds);

     if(mc != CURLM_OK)
     {
        break;
     }

    if(!numfds) 
    {
      repeats++; /* count number of repeated zero numfds */
      if(repeats > 1) 
      {
        Sleep(100); /* sleep 100 milliseconds */
      }
    }
    else
      repeats = 0;
    
    int         msgs_left;
    CURLMsg *   msg;
    while((msg = curl_multi_info_read(m_phttpQuestList, &msgs_left)))
    {
        if (CURLMSG_DONE == msg->msg)
        {
           ....
        }

    }

 } while(RunningNum);

curl_multi_perform will insert the number of requests remaining in the running thread into RunningNum. If the RunningNum is greater than 0, you should call the curl_multi_perform continuously. The curl_multi_info_read can get if there is any request finished.

OK, that's all.

History

  • 2015.11.26: The first edition

License

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