Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

libcurl HTTPS POST data send?

Tags:

c

libcurl

I have application that received data via HTTP POST requests. I'm trying to use libcurl to open a request to this app, send the data and receive the reply back from the app. This is the code I have so far:

int main(void)
{
    CURL *curl;
    CURLcode res;

    curl = curl_easy_init();
    if(curl) 
    {
        const int timeout = 30000;
        char outputmessage[]="VGhpcyBpcyBqdXN0IGEgbWVzc2FnZSwgaXQncyBub3QgdGhlIHJlYWwgdGhpbmc=";

        curl_easy_setopt(curl, CURLOPT_URL, "https://somehost.com/someapp");
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.5");
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, outputmessage);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(outputmessage));
        curl_easy_setopt(curl, CURLOPT_POST, 1L);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout/1000);

        res = curl_easy_perform(curl);
        if(CURLE_OK != res)
        {
            printf("Error: %s\n", strerror(res));
            return 1;
        }

        // now what?

        // cleanup when done
        curl_easy_cleanup(curl);
    }
    return 0;
}

This essentially connects to the server, I get a OK on the curl_easy_perform(). I can see the connection on Wireshark.

Two questions:

1) Is this the correct way of sending data via a POST, and
2) How do I get the reply from the application.

I thought I need to use curl_easy_recv() but I can't see how. Any sample code is welcome. Thanks.

like image 761
Mr Aleph Avatar asked Oct 21 '11 14:10

Mr Aleph


2 Answers

I think you should also consider adding a handler for the response headers:

cres = curl_easy_setopt( handle, CURLOPT_HEADERFUNCTION, HandleHeader );

It may be that if this is a web service designed for use by an application, its reply is a header-only reply, with no response data. The header would contain data such as:

HTTP/1.1 200 OK ...

Where the main thing you're looking for is the 200 code saying the request was OK.

The functions to handle the data from either header or response should take a void*, and you'll need to null-terminate it if you're using it as a string. For info this is how I handle the incoming data (in this case I only use the return code in my application - the response body just goes to a log file):

static size_t CurlHandleResponse(
  void *Ptr,
  size_t Size,
  size_t NoElements,
  void* Data )
{
  memcpy( &( gData[gDataLen] ), Ptr, (Size * NoElements) );
  gDataLen += (Size * NoElements);
  gData[ gDataLen ] = '\0';
  return (Size * NoElements);
}

...
ConvertUnprintable( gData, PrintStr );
...

Error handling removed for brevity!

like image 96
asc99c Avatar answered Nov 15 '22 05:11

asc99c


You don't need to call any receive function. The received response comes back to you when control passes to the write-finished callback. Set up that callback something like this:

curl_res = curl_easy_setopt( handle, CURLOPT_WRITEFUNCTION, RecvResponseCallback );

before calling perform.

Define the callback like this:

size_t
RecvResponseCallback ( char *ptr, size_t size, size_t nmemb, char *data ) {
  // handle received data
  return size * nmemb;
}

The response data is pointed by the data arg (not the ptr arg, which is something else that you will want to look at when you get this working).

When you exit RecvResponseCallback, be sure to return (size_t) size * nmemb

like image 35
Pete Wilson Avatar answered Nov 15 '22 05:11

Pete Wilson