The C++ REST SDK ("Casablanca")

The C++ REST SDK ("Casablanca")

Rate This
  • Comments 20

The C++ REST SDK (codename "Casablanca") has officially been released as an open source project on CodePlex (http://casablanca.codeplex.com).

We first announced Casablanca as an incubation project on Microsoft's DevLabs back in April of 2012. Since then we have had several releases and have seen library quickly evolve. As we added new features and received feedback from customers, it was evident that two separate entities were beginning to form. As a result, the "Casablanca" project on DevLabs has been separated into 2 different SDKs: the C++ REST SDK and the Azure SDK for C++.

 The first of the two SDKs being released is the C++ REST SDK. It includes tools to quickly write modern, asynchronous C++ code that connects with REST services. We take advantage of the power and productivity offered in C++11 while providing a cross-platform solution. We currently support Windows 7, Windows 8 (Windows store and desktop applications), and Linux.

 The main features in this SDK include:

  • Ability to create a connection to a server via a HTTP Client, send requests and handle response.
  • Support for construction and use of Uniform Resource Identifiers (URI).
  • Constructing, parsing and serializing JSON values.
  • Asynchronously reading/writing bytes to/from an underlying medium via Streams and Stream Buffers.

Let's look at some code to get a glimpse of the aforementioned features in action.

This first example is a simple application that uploads a file to an HTTP Server. 

#include <http_client.h>
#include<filestream.h>
#include <uri.h>

using namespace concurrency::streams;
using namespace web::http::client;
using namespace web::http;

int main()
{
  // Open stream to file.
  file_stream<unsigned char>::open_istream(L"myfile.txt").then([](basic_istream<unsigned char> fileStream)
  {
    // Make HTTP request with the file stream as the body.
    http_client client(L"http://www.myhttpserver.com");
    client.request(methods::PUT, L
"myfile", fileStream).then([fileStream](http_response response)
    {
      fileStream.close();
      // Perform actions here to inspect the HTTP response...
      if(response.status_code() == status_codes::OK)
      {
      }
    });
  });

  return 0;
}

We use the concurrency::streams::file_stream class to asynchronously read a file from disk. The constructor of the file stream returns a PPL task of a basic_istream.

Within the continuation we create an instance of http_client to represent the connection to the server. Using this instance we can now send requests. In this example we use the web::http::methods::PUT to specify the operation as an HTTP PUT request. We also include the name of the file and the file stream in our request. Finally, we capture the http_response in a continuation and perform the necessary actions to inspect if the request was successfully processed by the server.

This example illustrates how straight-forward writing a responsive client application that connects to a service can be.

Next we will demonstrate how to build a JSON value in memory and loop through its values.

#include <json.h>

int main()
{
  // Create a JSON object.
  json::value obj;
  obj[L
"key1"] = json::value::boolean(false);
  obj[L
"key2"] = json::value::number(44);
  obj[L
"key3"] = json::value::number(43.6);
  obj[L
"key4"] = json::value::string(U("str"));

  // Loop over each element in the object.
  for(auto iter = obj.cbegin(); iter != obj.cend(); ++iter)
  {
    // Make sure to get the value as const reference otherwise you will end up copying
    // the whole JSON value recursively which can be expensive if it is a nested object.
    const json::value &str = iter->first;
    const json::value &v = iter->second;

    // Perform actions here to process each string and value in the JSON object...
    wprintf(L"String:%s", str.as_string());
    wprintf(L
"Value:%s", v.to_string());
  }
  return 0;
}

In the C++ REST SDK all JSON values are represented by the web::json::value class. In the example we build our JSON object using the value factory functions. A JSON value can also be parsed from a stream using a constructor that takes a stream reference. Once we have our JSON value we can use the cbegin and cend methods to return read-only iterators for the value collection.

Including this simple yet powerful representation of JSON objects in the SDK, provides developers with a set of tools that are productive and compose well together.

Thanks for taking the time to read this post, we hope that everyone gets a chance to visit the project on CodePlex, we would love to hear your feedback.

Stay tuned for more updates about both the C++ REST SDK and the Azure SDK for C++. A special thanks to Steve Gates for reviewing this post and providing the code snippets.

  • Our respect to the Microsoft developers who have created this library! www.viva64.com/.../0189

  • In the second example, the two lines in thwith wprintf() calls should read this:

       wprintf(L"String:%s\n", str.as_string().c_str());

       wprintf(L"Value:%s\n", v.to_string().c_str());

  • @Joshua Warner

    You may wish to vote up for casablanca.codeplex.com/.../5

  • Is the call

    `file_stream<unsigned char>::open_istream(L"myfile.txt")`

    asynchronous? I am assuming it is because of the `.then(` following it. Judging by this, it looks like the program is able to terminate by the time the `then` continuation will be called. Shouldn't a `wait()` be in there somewhere?

  • @ Zadirion

    Yes you are correct, this is asynchronous code and therefore a wait() would be appropriate here to make sure the task completes.

Page 2 of 2 (20 items) 12