cURL Example
============
Overview
--------
This example shows how [cURL](http://curl.haxx.se) can be used with gSOAP's [CURL plugin](https://www.genivia.com/doc/curl/html/index.html) to let cURL handle all HTTP/s over TCP/IP traffic instead of gSOAP's HTTP/S stack. A SOAP/XML calculator client example and a JSON example are presented.
The examples shown use the CURL plugin where the plugin creates an internal local CURL handle to communicate with the server. You can also create your own CURL handle and register it with the CURL plugin. The benefit is that you can set any of the CURL handle options yourself. See the [CURL plugin](https://www.genivia.com/doc/curl/html/index.html) documentation for details.
Implementing the calculator client application
----------------------------------------------
To use [cURL](http://curl.haxx.se), register the [CURL plugin](https://www.genivia.com/doc/curl/html/index.html) for gSOAP using `soap_register_plugin(soap, soap_curl)`. Add `curl_global_init(CURL_GLOBAL_ALL)` to the start of your program and add `curl_global_cleanup()` to the end of your program. As an example we will use the source code of the [C calculator client example](../calc) and the [C++ calculator client example](../calc++) as shown in the example code below.
This simple client application is run at the command line with command-line parameters to add, subtract, multiply, divide, or raise two values:
[codetab.C]
#include "soapH.h"
#include "calc.nsmap"
#include "plugin/curlapi.h" /* we need the CURL plugin */
/* the Web service endpoint URL */
const char server[] = "http://localhost:8080";
int main(int argc, char **argv)
{
struct soap *soap = soap_new1(SOAP_XML_INDENT); /* new context */
double a, b, result;
if (argc < 4)
{
fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num\n");
exit(0);
}
curl_global_init(CURL_GLOBAL_ALL); /* initialize cURL */
soap_register_plugin(soap, soap_curl); /* register the CURL plugin */
a = strtod(argv[2], NULL);
b = strtod(argv[3], NULL);
switch (*argv[1])
{
case 'a':
soap_call_ns__add(soap, server, "", a, b, &result);
break;
case 's':
soap_call_ns__sub(soap, server, "", a, b, &result);
break;
case 'm':
soap_call_ns__mul(soap, server, "", a, b, &result);
break;
case 'd':
soap_call_ns__div(soap, server, "", a, b, &result);
break;
case 'p':
soap_call_ns__pow(soap, server, "", a, b, &result);
break;
default:
fprintf(stderr, "Unknown command\n");
exit(0);
}
if (soap->error)
{
soap_print_fault(soap, stderr);
soap_curl_reset(soap); /* reset the CURL plugin after an error */
}
else
{
printf("result = %g\n", result);
}
soap_destroy(soap); /* delete deserialized objects */
soap_end(soap); /* delete heap and temp data */
soap_free(soap); /* we're done with the context */
curl_global_cleanup(); /* we're done with cURL */
return 0;
}
[codetab.C++]
#include "soapcalcProxy.h"
#include "calc.nsmap"
#include "plugin/curlapi.h" /* we need the CURL plugin */
/* the Web service endpoint URL */
const char server[] = "http://localhost:8080";
int main(int argc, char **argv)
{
if (argc < 4)
{
fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num\n");
exit(0);
}
calcProxy calc(server);
curl_global_init(CURL_GLOBAL_ALL); /* initialize cURL */
soap_register_plugin(calc.soap, soap_curl); /* register the CURL plugin */
double a, b, result;
a = strtod(argv[2], NULL);
b = strtod(argv[3], NULL);
switch (*argv[1])
{
case 'a':
calc.add(a, b, &result);
break;
case 's':
calc.sub(a, b, &result);
break;
case 'm':
calc.mul(a, b, &result);
break;
case 'd':
calc.div(a, b, &result);
break;
case 'p':
calc.pow(a, b, &result);
break;
default:
fprintf(stderr, "Unknown command\n");
exit(0);
}
if (calc.soap->error)
{
calc.soap_stream_fault(std::cerr);
soap_curl_reset(calc.soap); /* reset the CURL plugin after an error */
}
else
{
std::cout << "result = " << result << std::endl;
}
calc.destroy(); /* clean up */
curl_global_cleanup(); /* we're done with cURL */
return 0;
}
Resetting the CURL plugin after an error ensures that normal gSOAP inout/output operations, such as serializing data to files and steams, are no longer controlled by the CURL plugin.
[![To top](../../images/go-up.png) To top](#)
Build steps for the calculator client application
-------------------------------------------------
The build steps are the same as presented in the [C calculator client example](../calc) and the [C++ calculator client example](../calc++) except that we also should compile `plugin/curlapi.c` and link with libcurl.
[![To top](../../images/go-up.png) To top](#)
Running the calculator client application
-----------------------------------------
[command]
./calcclient add 2 3
result = 5
[![To top](../../images/go-up.png) To top](#)
Implementing the JSON application
---------------------------------
For this example we will use the source code of the [C JSON example](../json) and the [C++ JSON example.](../json++)
This simple JSON application is run at the command line and displays the current time:
[codetab.C]
#include "json.h"
#include "plugin/curlapi.h"
int main()
{
struct soap *ctx = soap_new1(SOAP_C_UTFSTRING | SOAP_XML_INDENT);
struct value *request = new_value(ctx);
struct value response;
ctx->send_timeout = 10; /* 10 sec, stop if server is not accepting msg */
ctx->recv_timeout = 10; /* 10 sec, stop if server does not respond in time */
curl_global_init(CURL_GLOBAL_ALL); /* initialize cURL */
soap_register_plugin(ctx, soap_curl); /* register the CURL plugin */
/* make the JSON REST POST request and get response */
*string_of(request) = "getCurrentTime";
if (json_call(ctx, "http://localhost:8080", request, &response))
soap_print_fault(ctx, stderr);
else if (is_string(&response)) /* JSON does not support a dateTime value: this is a string */
printf("Time = %s\n", *string_of(&response));
else /* error? */
{
printf("Error: ");
json_write(ctx, &response);
soap_curl_reset(ctx); /* reset the CURL plugin after an error */
}
/* clean up */
soap_destroy(ctx);
soap_end(ctx);
soap_free(ctx);
curl_global_cleanup(); /* we're done with cURL */
return 0;
}
/* Don't need a namespace table. We put an empty one here to avoid link errors */
struct Namespace namespaces[] = { {NULL, NULL} };
[codetab.C++]
#include "json.h"
#include "plugin/curlapi.h"
using namespace std;
int main()
{
soap *ctx = soap_new1(SOAP_C_UTFSTRING | SOAP_XML_INDENT);
ctx->send_timeout = 10; // 10 sec, stop if server is not accepting msg
ctx->recv_timeout = 10; // 10 sec, stop if server does not respond in time
curl_global_init(CURL_GLOBAL_ALL); /* initialize cURL */
soap_register_plugin(ctx, soap_curl); /* register the CURL plugin */
value request(ctx), response(ctx);
// make the JSON REST POST request and get response
request = "getCurrentTime";
if (json_call(ctx, "http://localhost:8080", request, response))
soap_print_fault(ctx, stderr);
else if (response.is_string()) // JSON does not support a dateTime value: this is a string
cout << "Time = " << response << endl;
else // error?
{
cout << "Error: " << response << endl;
soap_curl_reset(ctx); /* reset the CURL plugin after an error */
}
// clean up
soap_destroy(ctx);
soap_end(ctx);
soap_free(ctx);
curl_global_cleanup(); /* we're done with cURL */
return 0;
}
/* Don't need a namespace table. We put an empty one here to avoid link errors */
struct Namespace namespaces[] = { {NULL, NULL} };
Build steps for the JSON application
------------------------------------
The build steps are the same as presented in the [C JSON example](../json) and the [C++ JSON example](../json++) except that we also should compile `plugin/curlapi.c` and link with libcurl.
[![To top](../../images/go-up.png) To top](#)
Running the JSON application
----------------------------
[command]
./currentTime
Time = 2017-06-05T17:26:12Z
[![To top](../../images/go-up.png) To top](#)