C++

Levando os serviços RESTful até os desenvolvedores de C++

Sridhar Poduri

Baixar o código de exemplo

Neste artigo eu vou mostrar como usar o SDK do resto de C++ para criar um aplicativo simples cliente baseado em Windows que carrega um arquivo para o Dropbox, juntamente com uma classe de C++ padrão que suporta o OAuth.

O mundo de dispositivos conectados cada vez mais avança em uma mistura heterogênea de aplicativos nativos, aplicativos Web e sites da Web conectando todos para um mix de serviços e não-nuvem-baseada em nuvem. Esses aplicativos compartilham e consomem dados através desta mistura de dispositivos e serviços e proporcionam experiências de imersão para usuários finais. Esses usuários são cada vez mais usando apps instalados em seus dispositivos pessoais (smartphones, tablets, PCs e outros dispositivos similares). Os desenvolvedores são incumbidos de criar experiências sem emenda naqueles apps para facilitar a partilha, organização e visualização de dados — e para usuários de deleite.

Apps são escritos em uma variedade de linguagens de programação. Alguns, tais como PHP, c# e Java, são por padrão habilitado para Web e pode satisfazer as necessidades de alguns dos cenários comuns para compartilhamento e consumir dados. Em outros casos, bibliotecas especializadas podem ser utilizadas para realizar do lado do servidor de computação, processamento e análise e retornar uma resposta ao cliente app.

No seu livro, "Welcome to the Jungle" (bit.ly/uhfrzH), Herb Sutter, inequivocamente, descreve o movimento mainstream para elástico, distribuídos de computação como uma evolução natural da mesma escala e desempenho de tendências que tem conduzido com vários núcleos e heterogêneo de computação para o mainstream.

C++ é a linguagem de programação preferida quando o compartilhamento de código cross-plataforma e desempenho são considerações de design. Quando se trata de computação em nuvem, porém, C++ aparentemente não entregar em todo o seu potencial. Um dos principais motivos citados para este aparente fracasso é a falta de uma biblioteca multiplataforma, alto desempenho, eficiente, escalável que permitiria um desenvolvedor C++ integrar código C e C++ existente no ambiente de nuvem.

O SDK do resto de C++ (bit.ly/VI67I5) é primeira incursão da Microsoft permitindo código nativo para mover para o ambiente de nuvem. Visa fornecer aos desenvolvedores ferramentas e APIs que resolver problemas do dia a dia de mover o código nativo para a nuvem. A versão inicial é uma biblioteca de cliente, cross-platform para acessar outros serviços. O objetivo é tornar o SDK de resto C++ uma biblioteca verdadeiramente multi-plataforma que pode desbloquear o verdadeiro potencial de código nativo na nuvem. O SDK do resto de C++ podem ser a base da construção de bibliotecas mais especializadas, tais como aqueles para apoiar a criação de serviços do Windows Azure, e permitirá que leve, de alto desempenho de serviços Web ser escrito em código C++ portátil sem a necessidade de estruturas adicionais ou runtimes para ser implantado em cloud-based máquinas virtuais (VMs).

Por que escolher o SDK do resto de C++?

Para acessar os serviços REST, um desenvolvedor C++ pode construir abstrações sobre as APIs do C-estilo como WinINet ou WinHTTP no Windows e APIs similares em outras plataformas. Dadas tais opções, é uma pergunta que exige uma resposta imediata: Por que o desenvolvedor deve escolher SDK do resto do C++?

O SDK do resto de C++ é projetado e escrito a partir do zero usando C++ moderno. As características incluem:

  • Suporte para acesso a serviços baseados em REST do código nativo na Windows Vista, Windows 7, Windows 8, apps da loja do Windows e Linux, fornecendo ligações assíncronas para HTTP, JSON, XML, URIs, e assim por diante.
  • Uma extensão de Visual Studio SDK que permite o consumo do SDK no Windows Store apps.
  • Um modelo de programação consistente e poderoso para compor operações assíncronas baseado no padrão C + + 11 características.
  • Uma implementação assíncronos fluxos e buffers de fluxo que podem ser usados para ler e gravar fluxos de arquivo/dispositivo.

As Classes de cliente do resto de C++

RESTO de C++ é construído sobre a premissa de usar C++ moderno e padrões de programação assíncrona. Para as minhas experiências com o Dropbox, eu usei a classe http_client, as classes de tarefa e a classe assíncrona fluxos. Vamos discutir cada uma delas.

A classe http_client como o nome implica, a classe http_client do namespace web::http é usada para configurar e manter uma conexão a um serviço HTTP Web. Se você criar uma instância do http_client e um URI para o ponto de extremidade do serviço, a instância do objeto pode ser usada para fazer pedidos em nome do cliente. Assincronia é construída em à biblioteca de C++ resto, então respostas são retornadas pela biblioteca como tarefas.

A classe Task uma tarefa representa uma operação que potencialmente poderia terminar quando a função de produzir disse tarefa já retornou. Não todas as tarefas executadas para conclusão, e não há garantia na ordem de conclusão, também. Cada tarefa o objeto tem uma função de membro is_done, que retorna um bool. Quando a tarefa foi executado para conclusão, is_done retorna true; caso contrário, retornará false. Uma vez que uma tarefa foi executado para conclusão — conforme indicado pelo valor booleano retornado pela função de membro is_done — chamando a função get na tarefa retorna o valor fora da tarefa. Cuidado com os chamando a função get, quando a função is_done retorna false. Isso irá bloquear o thread e derrotar todo o propósito de construir padrões de assíncrono no código.

Em vez de continuamente à procura de is_done, é melhor usar a função então. Se baseia em anexar uma função de manipulador para a tarefa, similar às promessas em extensões JavaScript para Windows Store apps. Deve ser facilmente identificável para os desenvolvedores usando as tarefas PPL usadas para programação Windows Runtime (WinRT) operações assíncronas. A função de manipulador passada para a função então deve levar um argumento de tipo T ou tarefa <T>. Usando o argumento da tarefa tipo <T> concede um benefício adicional: É a única maneira de capturar exceções levantadas pela operação de tarefa em si!

Porque o manipulador para a função então é invocado apenas após a conclusão da tarefa, chamando a função get dentro o manipulador é seguro e não bloquear o thread.

Os fluxos de Asynchronous o resto do C++ library inclui um conjunto de classes auxiliares para ler e gravar objetos encapsulados como fluxos e buffers de fluxo. Seguir o padrão e a precedência definida na biblioteca C++ padrão, córregos e buffers em C++ resto separam a preocupação de formatação de dados para entrada e saída da preocupação de gravar e ler bytes ou coleções de bytes para e de algum meio subjacente como um soquete TCP, um arquivo de disco ou até mesmo um buffer de memória. De certa forma, fluxos são desconectados do meio subjacente usado para ler e gravar dados. A grande diferença com streams em C++ resto é que eles suportam leitura assíncrona e escrever operações, ao contrário de classes C++ padrão, que estão a bloquear. Como é o projeto com outros objetos do resto do C++, os métodos assíncronos em classes de fluxo de retornam um task <T> em vez de um valor.

Com esta cartilha no resto do C++, agora é hora de pensar sobre a API REST do Dropbox. No restante deste artigo, discutirei acessando a API REST Dropbox usando resto de C++ para carregar um arquivo no computador local executando o Windows para a pasta do usuário Dropbox.

A API REST do Dropbox

Dropbox usa OAuth versão 1 para autenticar todos os pedidos para sua API (bit.ly/ZJLP4o) e requer que todas as solicitações são feitas sobre SSL. Uma pesquisa na Internet para uma biblioteca de C++ padrão, suportando OAuth retorna apenas a biblioteca OAuth, liboauth, e requer também Open­SSL (bit.ly/BpfcH) ou serviços de segurança de rede (NSS) Mozilla (mzl.la/abU77o). Eu queria uma classe leve, multi-plataforma que suporta o OAuth, então prepare-se para construir um para oferecer suporte a autenticação do Dropbox.

Para gente curiosa, Brook Miles tem uma grande série de posts sobre como acessar o Twitter OAuth em C++ do Win32 (bit.ly/137Ms6y). Construído em cima de suas idéias básicas, mas refatorado o código para trabalhar com as APIs do Dropbox, usando os tipos de C++ padrão suportados pelo resto do C++, tanto quanto possível. Além disso, eu não pretendo usar WinINet ou WinHTTP para executar quaisquer solicitações da Web, como que me amarrava para plataforma Windows e me forçar a usar uma API de C-estilo.

Agora falarei sobre construir uma simples classe de C++ que suporta OAuth e um aplicativo Win32 usando resto de C++ que faz chamadas para o Dropbox e carrega um arquivo para o Dropbox. Em um artigo de acompanhamento, eu vou mostrar como usar o resto de C++ de uma app Store do Windows e fazer o upload de arquivos para o Dropbox.

Antes de começar a escrever um aplicativo que pode acessar o Dropbox, preciso registrá-lo com o Dropbox. Isso é feito no portal console Apps Dropbox (bit.ly/R14tjq). Me inscrevi para uma conta gratuita do Dropbox, logado no portal do console Apps e criou um novo app clicando no botão "Create-app".

O processo pede-lhe para escolher um nome de aplicativo, tipo de app e um tipo de permissão. Entrei de "testar" e escolheu o tipo de app do núcleo (ver Figura 1). Os outros tipos de app são Dropbox Chooser (útil para desenvolvedores de JavaScript) e API Sync (melhor para iOS e Android desenvolvedores). Finalmente, eu escolhi o tipo de permissão como Dropbox completo, como este me dá a flexibilidade de leitura, escrita e sincronização para qualquer pasta no Dropbox versus uma pasta específica, que é fornecida pelo tipo de permissão de pasta App "sandbox".

Choices for Creating a Dropbox App
Figura 1 opções para criar um App Dropbox

Ao clicar no botão "Create-app", o Dropbox cria o app e fornece detalhes necessários para acesso, como a chave do app, segredo de app e assim por diante, conforme mostrado no Figura 2. Eu fiz nota destes porque preciso deles para executar através de programação solicitações de autenticação e autorização usando OAuth.

Choosing Dropbox App Details
Figura 2-escolhendo Dropbox App detalhes

Uma simples classe de C++ multi-plataforma para OAuth

Agora para a ação real! Como eu disse anteriormente, eu queria escrever uma classe de plataformas que poderia ser usada em Windows e Linux. A versão atual do SDK do resto do C++ não oferece suporte a fazer solicitações HTTPS de uma caixa de Linux. Esta é uma decepção, e ouvi dizer que o suporte completo de HTTPS para Linux está chegando em breve. A classe C++ que discutir aqui deve funcionar no Windows e em Linux sem grandes modificações. Para oferecer suporte a autenticação baseada em OAuth para Dropbox, eu tive que cumprir os seguintes requisitos principais (consulte o site do Dropbox para requisitos de completo):

  • Todas as solicitações devem ser feitas sobre SSL. Isso significa usar apenas o HTTPS, versus HTTP.
  • OAuth requer esse pedido URIs e parâmetros ser assinado usando criptografia HMAC-SHA1 ou RSA-SHA1 ou texto sem formatação, se a solicitação for realizada em SSL.

Com a finalidade de minhas experiências, me acomodei na usando transporte de assinatura de texto sem formatação e fazendo pedidos via HTTPS. Construir uma criptografia API que funciona em Windows e Linux é complexo e demorado e vale a pena uma exploração detalhada mais tarde.

Uma vez me acomodei sobre os requisitos, que era hora de criar a classe. Declarei um namespace de alto nível, convenientemente chamado de autenticação e uma classe dentro nomeado oAuth. No nível de namespace, tive uns cordelinhos const declarados para os pontos de extremidade do URI, a app chave e segredo de app para app obtido no processo de registo de app e alguns métodos auxiliares, como mostrado na Figura 3.

Figura 3-construindo o oAuth classe

// 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";

O suporte de protocolo OAuth inteiro é implementado no método BuildSignedOAuthParameters da classe oAuth. Esse método aceita o ponto de extremidade URI, o tipo de método HTTP (GET, POST, PUT e assim por diante), a chave do app, segredo de app, de solicitação e segredo do símbolo e cria uma assinatura que deve ser enviada através de Dropbox com cada solicitação. Dropbox tenta construir a assinatura exata em sua extremidade usando os parâmetros passados com a solicitação HTTPS e coincidir com as assinaturas geradas. Se as assinaturas não coincidirem, ele retorna um código de erro HTTP.

Uma assinatura é construída usando um número aleatório — chamado um nonce no jargão OAuth — incluindo um carimbo de hora para o pedido, a versão do protocolo OAuth com suporte, o tipo de assinatura e muito mais. O método retorna uma lista de todos os parâmetros necessários, classificados por nome e com a assinatura URL codificado (consulte Figura 4).

Figura 4 uma assinatura de construção

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;
}

Com suporte para OAuth fora do caminho, eu escrevi o código do cliente para acessar os arquivos no Dropbox. Eu criei quatro métodos:

  1. oAuthLoginAsync: Executa o login para Dropbox usando o app chave e segredo.
  2. AuthorizeDropBoxAccess: Inicia o Internet Explorer e autoriza o acesso do app para o Dropbox. Este método é específico para Windows e inicia o Internet Explorer independentemente se é o navegador padrão.
  3. oAuthAcquireTokenAsync: Executa a ação para adquirir o token de acesso real do Dropbox.
  4. UploadFileToDropBoxAsync: Carrega um arquivo do sistema local para armazenamento em nuvem Dropbox.

Cada uma dessas operações é feita extremamente fácil e sem emenda usando as classes de cliente do resto do C++.

O código do cliente

Então, como é que código do cliente escrito usando C++ moderno com tarefas assíncronas igualar-se contra o uso de uma API de C-estilo? É hora de descobrir.

Com um estilo C API como WinINet, teria de fazer as seguintes chamadas de API do WinINet para fazer minha app funcionar:

  • Construa manualmente o cabeçalho de solicitação HTTP.
  • Chame InternetCrackUrl para resolver o URL de ponto de extremidade do resto.
  • Chamar InternetOpen e obter um identificador para a conexão de Internet. Normalmente isto é retornado como uma instância HINTERNET.
  • Uma vez eu tive um identificador válido de HINTERNET, fazer uma chamada para Http­OpenRequest, que retorna outra instância de HINTERNET.
  • Fazer a próxima chamada para HttpAddRequestHeaders, que retorna um valor booleano indicando se as informações de cabeçalho foi adicionadas com sucesso à solicitação HTTP.
  • Assim que concluí com sucesso todas as etapas anteriores com a manipulação de erro apropriado colocar no lugar, fazer a chamada para HttpSendRequest, que envia a solicitação real.
  • Ao receber uma resposta à solicitação anterior, fazer outra chamada para inicializaçãoInternetReadFile para ler o fluxo de resposta.

Por favor, note que todas as APIs anteriores são APIs C-estilo com nenhum suporte para modernos idiomas de programação C++ como ponteiros compartilhados, lambdas e padrões assíncrona construídos em.

Agora para o código real usando o SDK do resto de C++. Figura 5 mostra a função de oAuthLoginAsync, que executa a operação de logon para o Dropbox e a função UploadFileToDropBoxAsync que carrega um arquivo do sistema local para o Dropbox.

Figura 5 o oAuthLoginAsync função

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);
    });
  });
}

Na função oAuthLoginAsync, eu primeiro construir uma instância URI de uma representação de seqüência de caracteres do ponto de extremidade URI de Login. Em seguida, criar uma instância da classe oAuth e chamar a função de membro CreateOAuthSignedParameters, que cria um mapa que contém todos os os OAuth solicitação parâmetros necessários. Finalmente, eu assino os cabeçalhos, chamando a função de membro OAuthBuildSignedHeaders. Assinatura dos cabeçalhos é obrigatória de acordo com a especificação do OAuth. A comunicação HTTP começa agora. Eu só precisa criar uma instância de um http_client e aprovado a sequência de solicitação assinada. Dropbox vai usar a seqüência de solicitação e informações de cabeçalho e a tentativa de construir o mesmo solicitar a seqüência de caracteres no lado do servidor e combiná-lo contra o que eu enviar como parte da solicitação HTTP. Se as seqüências de caracteres correspondem, recebo um código de retorno de sucesso; caso contrário, eu recebo um erro.

Eu iniciar o processo de comunicação, criando uma instância da classe http_client e em seguida, chamar a função de membro do pedido. Para especificar o método HTTP como obter. Quando o método de solicitação termina a execução, ele retorna um objeto http_response que eu uso para analisar e extrair o token e token segredo, que são armazenados em uma instância da classe app_credentials. O token deve ser enviado juntamente com todas as solicitações subseqüentes API para o Dropbox.

A função UploadFileToDropBoxAsync é mostrada na Figura 6. Segue-se um padrão semelhante à função oAuthLoginAsync até eu construir cabeçalhos de OAuth assinados. Uma vez eu construo as informações de cabeçalho, criar uma tarefa que lê um arquivo de sistema de arquivos local em um objeto file_stream e define esse objeto file_stream como o corpo da solicitação HTTP. Então pode criar uma instância de uma classe http_client e defina a instância de solicitação, que contém o conteúdo de file_stream como o corpo, e coloque a solicitação PUT. Após a conclusão, recebo uma tarefa que contém um http_response que pode ser analisado para o sucesso ou fracasso. É realmente bem simples.

Figura 6 a função de UploadFileToDropBoxAsync

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();
      }
  });
}

Quando comparado ao usando uma API de C-estilo de comunicação Web ou descendo a rota de construir o suporte usando plataforma -­APIs específicas tais como WinINet, o código escrito usando C++ moderno é mais sucinto, legível e elegante. Por uma questão de fato, todos os detalhes de implementação de baixo nível são abstraídos da interface pública da biblioteca. O SDK do resto de C++ baseia-se na promessa de C++ moderno e aplica os mesmos princípios de design para comunicação RESTful. O resultado final é uma biblioteca extremamente bem desenhada e modelada usando C++ moderno que torna o processo de construção de aplicativos conectados fácil e sem costura.

Próximo: Um App Store do Windows

Neste artigo, já explorei como construir um aplicativo simples cliente baseado no Windows usando o SDK do resto de C++ que carrega um arquivo para o Dropbox. Ao longo do caminho, eu também tenho discutido construindo uma classe de C++ padrão que suporta o OAuth. Em um artigo de acompanhamento, eu vou mostrar como construir uma app Store do Windows usando o SDK do resto de C++. Fique sintonizado!

Sridhar Poduri é gerente de programa da equipe do Windows da Microsoft. Um aficionado do C++ e autor do livro, "Modern C++ e Windows Apps da loja" (Sridhar Poduri, 2013), ele blogs regularmente sobre o C++ e o tempo de execução do Windows em sridharpoduri.com.

Agradecemos ao seguinte especialista técnico pela revisão deste artigo: Artur Laksberg (Microsoft)
Artur Laksberg é um líder de desenvolvimento sênior trabalhando na equipe do SDK do resto de C++.