Share via



August 2013

Volume 28 Number 8

C++ - Bringing RESTful Services to C++ Developers

By Sridhar Poduri

In this article I’ll show how to use the C++ REST SDK to build a simple Windows-based client application that uploads a file to Dropbox, along with a standard C++ class that supports OAuth.

The world of connected devices is increasingly moving into a heterogeneous mixture of native apps, Web apps and Web sites all connecting to a mix of cloud- and non-cloud-based services. These apps share and consume data through this mishmash of devices and services and provide rich, immersive experiences for end users. These users are increasingly using apps installed on their personal devices (smartphones, tablets, PCs and other similar devices). Developers are tasked with creating seamless experiences in those apps to facilitate sharing, organizing and viewing data—and to delight users.

Apps are written in a variety of programming languages. Some, such as PHP, C#, and Java, are by default Web-enabled and might meet the needs of some of the common scenarios for sharing and consuming data. In other cases, specialized libraries might be utilized to perform server-side computing, processing, and analysis, and return a response to the client app.

In his paper, “Welcome to the Jungle” (bit.ly/uhfrzH), Herb Sutter unambiguously describes the mainstream move to elastic, distributed computing as a natural evolution of the same scale and performance trends that have driven multicore and heterogeneous computing into the mainstream.

C++ is the preferred programming language when cross-platform code sharing and performance are design considerations. When it comes to cloud computing, though, C++ seemingly doesn’t deliver on its full potential. One of the primary reasons cited for this apparent failure is the lack of a cross-platform, high-performance, efficiently scalable library that would enable a C++ developer to seamlessly integrate existing C and C++ code into the cloud environment.

The C++ REST SDK (bit.ly/VI67I5) is Microsoft’s first foray into enabling native code to move to the cloud environment. It aims to provide developers with tools and APIs that solve day-to-day problems of moving native code to the cloud. The initial release is a client-side, cross-platform library to access REST services. The goal is to make the C++ REST SDK a truly cross-platform library that can unlock the true potential of native code in the cloud. The C++ REST SDK can be the basis of building more specialized libraries such as those to support Windows Azure services authoring, and it will enable lightweight, high-performance Web services to be written in portable C++ code without the need for additional frameworks or runtimes to be deployed on cloud-based virtual machines (VMs).

Why Choose the C++ REST SDK?

For accessing REST services, a C++ developer can build abstractions over the C-style APIs such as WinINet or WinHTTP on Windows and similar APIs on other platforms. Given such options, one question that calls for an immediate answer is: Why should a developer choose the C++ REST SDK?

The C++ REST SDK is designed and written from the ground up using modern C++. Features include:

  • Support for accessing REST-based services from native code on Windows Vista, Windows 7, Windows 8, Windows Store apps, and Linux by providing asynchronous bindings to HTTP, JSON, XML, URIs, and so on.
  • A Visual Studio Extension SDK that allows the consumption of the SDK in Windows Store apps.
  • A consistent and powerful programming model for composing asynchronous operations based on standard C++11 features.
  • An implementation of asynchronous streams and stream buffers that can be used to read and write to file/device streams.

The C++ REST Client Classes

C++ REST is built on the premise of using modern C++ and asynchronous programming patterns. For my experiments with Dropbox, I’ve used the http_client class, the Task classes and the asynchronous streams class. I’ll discuss each.

The http_client Class As the name implies, the http_client class from the web::http namespace is used to set up and maintain a connection to an HTTP Web service. If you create an instance of the http_client and a URI to the service endpoint, the object instance can be used to make requests on behalf of the client. Asynchrony is built in to the C++ REST library, so responses are returned by the library as tasks.

The Task Class A task represents an operation that could potentially finish when the function producing said task has already returned. Not all tasks run to completion, and there’s no guarantee in the order of completion, either. Each task object has a member function, is_done, which returns a bool. When the task has run to completion, is_done returns true; otherwise, it returns false. Once a task has run to completion—as indicated by the Boolean value returned by the is_done member function—calling the get function on the task returns the value out of the task. Beware of calling the get function when the is_done function returns false. Doing so will block the thread and defeat the whole purpose of building asynchronous patterns in code.

Instead of continuously checking for is_done, it’s better to use the then function. It relies on attaching a handler function to the task, similar to promises in JavaScript extensions for Windows Store apps. It should be easily identifiable for developers using the PPL tasks used for programming Windows Runtime (WinRT) asynchronous operations. The handler function passed to the then function should take an argument either of type T or task<T>. Using the argument of type task<T> bestows an additional benefit: It’s the only way to catch exceptions raised by the task operation itself!

Because the handler for the then function is invoked only after the task is completed, calling the get function inside the handler is safe and doesn’t block the thread.

The Asynchronous Streams The C++ REST library includes a set of helper classes to read and write to objects encapsulated as streams and stream buffers. Following the pattern and precedence set in the standard C++ library, streams and buffers in C++ REST separate the concern of formatting data for input and output from the concern of writing and reading bytes or collections of bytes to and from some underlying medium such as a TCP socket, a disk file or even a memory buffer. In a way, streams are disconnected from the underlying medium used to read and write data. The big difference with streams in C++ REST is that they support asynchronous read and write operations, unlike standard C++ classes, which are blocking. As is the design with other C++ REST objects, the asynchronous methods in the stream classes return a task<T> instead of a value.

With this primer on C++ REST, it’s now time to think about the Dropbox REST API. In the rest of this article, I’ll discuss accessing the Dropbox REST API using C++ REST to upload a file from the local machine running Windows to the user’s Dropbox folder.

The Dropbox REST API

Dropbox uses OAuth version 1 to authenticate all requests to its API (bit.ly/ZJLP4o) and requires that all requests are made over SSL. An Internet search for a standard C++ library supporting OAuth returns only the OAuth library, liboauth, and it requires either Open­SSL (bit.ly/BpfcH) or Mozilla Network Security Services (NSS) (mzl.la/abU77o). I wanted a lightweight, cross-platform class that supports OAuth, so I set out to build one to support Dropbox authentication.

For curious folks, Brook Miles has a great series of posts on accessing Twitter OAuth in C++ from Win32 (bit.ly/137Ms6y). I’ve built upon his basic ideas but refactored the code to work with the Dropbox APIs, using the standard C++ types supported by C++ REST as much as possible. In addition, I didn’t intend to use either WinINet or WinHTTP to perform any Web requests, as that would tie me to the Windows platform only and force me to use a C-style API.

Now I’ll discuss building a simple C++ class that supports OAuth and a Win32 application using C++ REST that makes calls to Dropbox and uploads a file to Dropbox. In a follow-up article, I’ll show how to use C++ REST from a Windows Store app and upload files to Dropbox.

Before I begin writing an application that can access Dropbox, I need to register it with Dropbox. This is done at the Dropbox Apps console portal (bit.ly/R14tjq). I signed up for a free Dropbox account, logged into the Apps console portal and created a new app by clicking on the “Create app” button.

The process asks you to choose an app name, app type and a permission type. I entered “test” and chose the app type Core (see Figure 1). The other app types are Dropbox Chooser (useful for JavaScript developers) and Sync API (best for iOS and Android developers). Finally, I chose the permission type as Full Dropbox, as this gives me the flexibility of reading, writing and syncing to any folder on Dropbox versus a specific folder, which is provided by the “sandbox” App folder permission type.

Choices for Creating a Dropbox App
Figure 1 Choices for Creating a Dropbox App

Upon clicking the “Create app” button, Dropbox creates the app and provides details needed for access, such as the app key, app secret and so on, as shown in Figure 2. I made note of these because I need them to perform programmatic authentication and authorization requests using OAuth.

Choosing Dropbox App Details
Figure 2 Choosing Dropbox App Details

A Simple Cross-Platform C++ Class for OAuth

Now for the real action! As I said earlier, I wanted to write a cross-platform class that could be used across both Windows and Linux. The current release of the C++ REST SDK doesn’t support making HTTPS requests from a Linux box. This is a disappointment, and I’ve heard that full HTTPS support for Linux is coming soon. The C++ class I discuss here should work across both Windows and Linux without major modifications. In order to support OAuth-based authentication for Dropbox, I had to meet the following main requirements (see the Dropbox site for full requirements):

  • All requests should be made over SSL. This means using only HTTPS, versus HTTP.
  • OAuth requires that request URIs and parameters be signed using either HMAC-SHA1 or RSA-SHA1 encryption, or plain text if the request is performed over SSL.

For the purpose of my experiments, I settled on using plain-text signature transport and making requests via HTTPS. Building an encryption API that works across both Windows and Linux is complex and time-consuming, and is worth a detailed exploration later.

Once I settled on the requirements, it was time to build the class. I declared a high-level namespace, conveniently called Authentication, and a class inside named oAuth. At the namespace level, I had a few const strings declared for the URI endpoints, the app key and app secret for the app obtained in the app registration process, and a few helper methods, as shown in Figure 3.

Figure 3 Building the oAuth Class

// Dropbox consumer key and secret
const std::wstring consumerKey = L"Your app key";
const std::wstring consumerSecret = L"Your app secret";
// List of Dropbox authenticate, authorize, request and file upload URIs
const std::wstring DropBoxRequestTokenURI =
  L"https://api.dropbox.com/1/oauth/request_token";
const std::wstring DropBoxAuthorizeURI =
  L"https://www.dropbox.com/1/oauth/authorize";
const std::wstring DropBoxAccessTokenURI =
  L"https://api.dropbox.com/1/oauth/access_token";
const std::wstring DropBoxFileUploadURI =
  L"https://api-content.dropbox.com/1/files_put/dropbox/<your file name here>";
const std::wstring LocalFiletoUpload = L"Your local file goes here";

The entire OAuth protocol support is implemented in the BuildSignedOAuthParameters method of the oAuth class. This method accepts the endpoint URI, the HTTP method type (GET, POST, PUT and so on), the app key, app secret, request token, and token secret, and builds a signature that should be sent across to Dropbox with each request. Dropbox attempts to build the exact signature on its end using the parameters passed with the HTTPS request and match the signatures generated. If the signatures don’t match, it returns an HTTP error code.

A signature is built using a random number—called a nonce in OAuth parlance—including a time stamp for the request, the version of OAuth protocol supported, the signature type and more. The method returns a list of all the required parameters, sorted by name and with the signature URL encoded (see Figure 4).

Figure 4 Building a Signature

HTTPParameters BuildSignedOAuthParameters( 
  const HTTPParameters& requestParameters,
  const std::wstring& url,
  const std::wstring& httpMethod,
  const HTTPParameters* postParameters,
  const std::wstring& consumerKey,
  const std::wstring& consumerSecret,
  const std::wstring& requestToken = L"",
  const std::wstring& requestTokenSecret = L""
  )
{
  std::wstring timestamp = OAuthCreateTimestamp();
  std::wstring nonce = OAuthCreateNonce();          

  m_oauthParameters[L"oauth_timestamp"] = timestamp;
  m_oauthParameters[L"oauth_nonce"] = nonce;
  m_oauthParameters[L"oauth_version"] = L"1.0";
  m_oauthParameters[L"oauth_signature_method"] = L"PLAINTEXT";
  m_oauthParameters[L"oauth_consumer_key"] = consumerKey;

  // Add the request token if found
  if (!requestToken.empty())
  {
    m_oauthParameters[L"oauth_token"] = requestToken;
  }

            
  // Create a parameter list containing both oauth and original
  // parameters; this will be used to create the parameter signature
  HTTPParameters allParameters = requestParameters;
  if(Compare(httpMethod, L"POST", false) && postParameters)
  {
    allParameters.insert(postParameters->begin(), 
      postParameters->end());
  }
  allParameters.insert(m_oauthParameters.begin(), 
    m_oauthParameters.end());

  // Prepare a signature base, a carefully formatted string containing 
  // all of the necessary information needed to generate a valid signature
  std::wstring normalUrl = OAuthNormalizeUrl(url);
  std::wstring normalizedParameters = 
    OAuthNormalizeRequestParameters(allParameters);

  std::wstring signatureBase = 
    OAuthConcatenateRequestElements(httpMethod, 
    normalUrl, 
    normalizedParameters);

  // Obtain a signature and add it to header requestParameters
  std::wstring signature = OAuthCreateSignature(signatureBase, 
    consumerSecret,
    requestTokenSecret);

  m_oauthParameters[L"oauth_signature"] = UrlEncode(signature);

  return m_oauthParameters;
}

With support for OAuth out of the way, I wrote the client code to access files on Dropbox. I created four methods:

  1. oAuthLoginAsync: Performs the login to Dropbox using the app key and secret.
  2. AuthorizeDropBoxAccess: Launches Internet Explorer and authorizes app access to Dropbox. This method is specific to Windows and launches Internet Explorer irrespective of whether it’s the default browser.
  3. oAuthAcquireTokenAsync: Performs the action to acquire the actual Dropbox access token.
  4. UploadFileToDropBoxAsync: Uploads a file from the local system to Dropbox cloud storage.

Each of these operations is made extremely easy and seamless using the C++ REST client classes.

The Client Code

So how does client code written using modern C++ with asynchronous tasks match up against using a C-style API? It’s time to find out.

With a C-style API such as WinINet, I would’ve had to make the following WinINet API calls to get my app working:

  • Manually build the HTTP request header.
  • Call InternetCrackUrl to resolve the REST endpoint URL.
  • Call InternetOpen and obtain a handle to the Internet connection. Typically this is returned as an HINTERNET instance.
  • Once I had a valid HINTERNET handle, make a call to Http­OpenRequest, which returns another instance of HINTERNET.
  • Make the next call to HttpAddRequestHeaders, which returns a Boolean value indicating if the header information has been added successfully to the HTTP request.
  • Once I successfully completed all the preceding steps with the appropriate error handling put in place, make the call to HttpSendRequest, which sends the actual request.
  • Upon receiving a response to the previous request, make another call to InternetReadFile to read the response stream.

Please note that all of the previous APIs are C-style APIs with no support for modern C++ programming idioms such as shared pointers, lambdas and asynchronous patterns built in.

Now for the actual code using the C++ REST SDK. Figure 5 shows the oAuthLoginAsync function, which performs the login operation to Dropbox and the UploadFileToDropBoxAsync function that uploads a file from the local system to Dropbox.

Figure 5 The oAuthLoginAsync Function

HTTPParameters BuildSignedOAuthParameters(
  const HTTPParameters& requestParameters,
  const std::wstring& url,
  const std::wstring& httpMethod,
  const HTTPParameters* postParameters,
  const std::wstring& consumerKey,
  const std::wstring& consumerSecret,
  const std::wstring& requestToken = L"",
  const std::wstring& requestTokenSecret = L""
  )
{
  std::wstring timestamp = OAuthCreateTimestamp();
  std::wstring nonce = OAuthCreateNonce();                                         
  m_oauthParameters[L"oauth_timestamp"] = timestamp;
  m_oauthParameters[L"oauth_nonce"] = nonce;
  m_oauthParameters[L"oauth_version"] = L"1.0";
  m_oauthParameters[L"oauth_signature_method"] = L"PLAINTEXT";
  m_oauthParameters[L"oauth_consumer_key"] = consumerKey;
  // Add the request token if found
  if (!requestToken.empty())
  {
    m_oauthParameters[L"oauth_token"] = requestToken;
  }
  // Create a parameter list containing both oauth and original
  // parameters; this will be used to create the parameter signature
  HTTPParameters allParameters = requestParameters;
  if(Compare(httpMethod, L"POST", false) && postParameters)
  {
    allParameters.insert(postParameters->begin(), 
      postParameters->end());
  }
  allParameters.insert(m_oauthParameters.begin(), 
    m_oauthParameters.end());
  // Prepare a signature base, a carefully formatted string containing
  // all of the necessary information needed to generate a valid signature
  std::wstring normalUrl = OAuthNormalizeUrl(url);
  std::wstring normalizedParameters =
    OAuthNormalizeRequestParameters(allParameters);
  std::wstring signatureBase =
    OAuthConcatenateRequestElements(httpMethod,
    normalUrl,
    normalizedParameters);
  // Obtain a signature and add it to header requestParameters
  std::wstring signature = OAuthCreateSignature(signatureBase,
    consumerSecret,
    requestTokenSecret);
  m_oauthParameters[L"oauth_signature"] = UrlEncode(signature);
  return m_oauthParameters;
}
task<void> oAuthLoginAsync(std::shared_ptr<app_credentials>& creds)
{           
  uri url(DropBoxRequestTokenURI);
  std::shared_ptr<oAuth> oAuthObj = std::make_shared<oAuth>();
  auto signatureParams =
   oAuthObj->CreateOAuthSignedParameters(url.to_string(),
   L"GET",
   NULL,
   consumerKey,
   consumerSecret
   );
  std::wstring sb = oAuthObj->OAuthBuildSignedHeaders(url);
  http_client client(sb);   
  // Make the request and asynchronously process the response
  return client.request(methods::GET)
    .then([&creds](http_response response)
  {                                          
    if(response.status_code() != status_codes::OK)
    {                             
      // Handle error cases ...
      return pplx::task_from_result();
    }
    // Perform actions here reading from the response stream ...
    // in this example, parse the response body and
    // extract the token and token secret
    istream bodyStream = response.body();
    container_buffer<std::string> inStringBuffer;
    return bodyStream.read_to_end(inStringBuffer)
      .then([inStringBuffer, &creds](pplx::task<size_t> previousTask)
    {
      const std::string &text = inStringBuffer.collection();
      // Convert the response text to a wide-character
      // string and then extract the tokens
      std::wstring_convert
        <std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf16conv;
      std::wostringstream ss;
      std::vector<std::wstring> parts;
      ss << utf16conv.from_bytes(text.c_str()) << std::endl;
      Split(ss.str(), parts, '&', false);
      unsigned pos = parts[1].find('=');
      std::wstring token = parts[1].substr(pos + 1, 16);
      pos = parts[0].find('=');
      std::wstring tokenSecret = parts[0].substr(pos + 1);
      creds->set_Token(token);
      creds->set_TokenSecret(tokenSecret);
    });
  });
}

In the oAuthLoginAsync function, I first construct a URI instance from a string representation of the Login URI endpoint. Next, I create an instance of the oAuth class and call the member function CreateOAuthSignedParameters, which builds a map containing all the necessary OAuth request parameters. Finally, I sign the headers by calling the OAuthBuildSignedHeaders member function. Signing of headers is mandatory as per the OAuth specification. The HTTP communication begins now. I need only create an instance of an http_client and pass it the signed request string. Dropbox will use the request string and header information and attempt to build the same request string on the server side and match it against what I send as part of the HTTP request. If the strings match, I get a success return code; otherwise, I get an error.

I begin the communication process by creating an instance of http_client class and then call the request member function. I specify the HTTP method as GET. When the request method finishes execution, it returns an http_response object that I use to parse and extract the token and token secret, which are stored in the app_credentials class instance. The token should be sent along with all subsequent API requests to Dropbox.

The UploadFileToDropBoxAsync function is shown in Figure 6. It follows a similar pattern to the oAuthLoginAsync function until I build the signed OAuth headers. Once I build the header information, I create a task that reads a file from the local file system into a file_stream object and sets that file_stream object as the HTTP request body. I can then create an instance of an http_client class and set the request instance, which contains the file_stream contents as the body, and place the PUT request. Upon completion, I get a task that contains an http_response that can be parsed for success or failure. It really is this simple.

Figure 6 The UploadFileToDropBoxAsync Function

task<void> UploadFileToDropBoxAsync(std::shared_ptr<app_credentials>& creds)
{
  using concurrency::streams::file_stream;
  using concurrency::streams::basic_istream;
  uri url(DropBoxFileUploadURI);
  std::shared_ptr<oAuth> oAuthObj = std::make_shared<oAuth>();
  auto signatureParams =     
    oAuthObj->CreateOAuthSignedParameters(url.to_string(),
    L"PUT",
    NULL,
    consumerKey,
    consumerSecret,
    creds->Token(),
    creds->TokenSecret()
    );
  std::wstring sb = oAuthObj->OAuthBuildSignedHeaders(url);
  return file_stream<unsigned char>::open_istream(LocalFiletoUpload)
    .then([sb, url](pplx::task<basic_istream<unsigned char>> previousTask)
  {
    try
    {
      auto fileStream = previousTask.get();
      // Get the content length, which is used to set the
      // Content-Length property
      fileStream.seek(0, std::ios::end);
      auto length = static_cast<size_t>(fileStream.tell());
      fileStream.seek(0, 0);
      // Make HTTP request with the file stream as the body
      http_request req;                                    
      http_client client(sb);                
      req.set_body(fileStream, length);
      req.set_method(methods::PUT);
      return client.request(req)
        .then([fileStream](pplx::task<http_response> previousTask)
      {
        fileStream.close();
        std::wostringstream ss;
        try
        {
          auto response = previousTask.get();
          auto body = response.body();                  
          ss << L"Server returned returned status code "
            << response.status_code() << L"."
            << std::endl;      
          std::wcout << ss.str();
        }
        catch (const http_exception& e)
        {
          ss << e.what() << std::endl;
             }
        std::wcout << ss.str();
      });
      }                       
      catch (const std::system_error& e)
      {
        std::wostringstream ss;
        ss << e.what() << std::endl;
        std::wcout << ss.str();
        // Return an empty task
        return pplx::task_from_result();
      }
  });
}

When compared to using a C-style API for Web communication or going down the route of building support using platform-­specific APIs such as WinINet, the code written using modern C++ is more succinct, readable and elegant. As a matter of fact, all of the low-level implementation details are abstracted away from the public interface of the library. The C++ REST SDK builds on the promise of modern C++ and applies the same design principles for RESTful communication. The end result is an extremely well-designed and patterned library using modern C++ that makes the process of building connected apps easy and seamless.

Next: A Windows Store App

In this article I’ve explored how to build a simple Windows-based client application using the C++ REST SDK that uploads a file to Dropbox. Along the way, I’ve also discussed building a standard C++ class that supports OAuth. In a follow-up article, I’ll show how to build a Windows Store app using the C++ REST SDK. Stay tuned!


Sridhar Poduri is a program manager in the Windows team at Microsoft. A C++ aficionado and author of the book, “Modern C++ and Windows Store Apps” (Sridhar Poduri, 2013), he blogs regularly about C++ and the Windows Runtime at sridharpoduri.com.

Thanks to the following technical expert for reviewing this article: Artur Laksberg (Microsoft)
Artur Laksberg is a senior development lead working in the C++ REST SDK team.