C++

Usando o C++ REST SDK em aplicativos da Windows Store

Sridhar Poduri

Baixar o código de exemplo

Em meu artigo anterior (msdn.microsoft.com/magazine/dn342869) apresentei o C++ REST SDK e como ele pode ser usado em aplicativos Win32/MFC. Neste artigo, discutirei como o C++ REST SDK pode ser integrado em aplicativos da Windows Store. Uma de minhas metas originais para uso do C++ REST SDK e da classe de autenticação OAuth era usar o C++ padrão ao máximo e fazer interface com as APIs específicas da plataforma apenas quando necessário. Esta é uma recapitulação rápida do artigo anterior:

  1. o código usado na classe de autenticação OAuth usa tipos padrão do C++ e nenhum tipo específico ao Windows.
  2. O código usado para fazer solicitações da Web ao serviço Dropbox REST usa os tipos do C++ REST SDK.
  3. O único código específico à plataforma é a função para iniciar o Internet Explorer e concluir a autenticação do aplicativo e a aprovação no portal do console de aplicativos do Dropbox.

Mantive as mesmas metas de meu aplicativo da Windows Store para dar suporte à autenticação e carregar um arquivo para o Dropbox. Esforcei-me para fornecer a maior quantidade possível de código C++ portável e para fazer interface com o WinRT (Tempo de Execução do Windows) apenas quando necessário. O código de exemplo dos dois artigos pode ser localizado em archive.msdn.microsoft.com/mag201308CPP.

Problemas com a solução Win32

Uma das maiores desvantagens do aplicativo Win32 anterior era a necessidade de iniciar um aplicativo externo para concluir o processo de autorização de OAuth. Isso significava que eu precisava iniciar o Internet Explorer (você também pode iniciar seu navegador favorito), fazer logon no Dropbox usando minhas credenciais e concluir o fluxo de trabalho. Isso é mostrado nas Figuras 1 e 2.

Logging in to Dropbox Using My Credentials Before Authorizing Application Access
Figura 1 Fazendo logon no Dropbox usando minhas credenciais antes de autorizar o acesso ao aplicativo

Successful Authorization for My Application on the Dropbox Portal
Figura 2 Autorização bem-sucedida para meu aplicativo no portal do Dropbox

Como você pode ver, iniciar um aplicativo externo e pedir aos usuários para concluírem o fluxo de trabalho por meio do aplicativo externo tira o foco de meu aplicativo. Como um desenvolvedor, também não tenho um mecanismo padrão por meio do qual meu aplicativo possa ser notificado quando o fluxo de trabalho for concluído. Com meu foco em programação assíncrona e com o C++ REST SDK projetado para dar suporte à programação baseada em tarefas assíncronas, iniciar um programa externo é claramente deprimente para mim. Explorei o uso de pipes nomeados, de arquivos mapeados para a memória etc., mas todas essas abordagens exigem que outro aplicativo seja escrito para hospedar uma instância de controle da Web e, em seguida, gravar o valor de êxito de volta por meio de um pipe nomeado, memória compartilhada ou de um arquivo mapeado para a memória. Finalmente, decidi usar o navegador para realizar a tarefa, porque não desejava escrever outro aplicativo encapsulado no controle do navegador.

Integrando com o Tempo de Execução do Windows

Ao começar a criar meu aplicativo para dar suporte ao Tempo de Execução do Windows, considerei algumas opções. Eu as listarei brevemente e, em seguida, discutirei a abordagem escolhida mais detalhadamente:

  1. usa ativação de protocolo e deixar que o sistema inicie o processo certo para identificar o protocolo chamando a função Windows::System::Launcher::LaunchUriAsync. Isso significa que, para um URI baseado em HTTPS, o sistema operacional iniciará o navegador padrão. É semelhante a iniciar o Internet Explorer no exemplo do Win32, mas com duas desvantagens: Meu aplicativo da Windows Store será enviado por push para o plano de fundo, o navegador padrão seria iniciado em tela inteira e, no pior cenário, meu aplicativo seria suspenso quando o fluxo de trabalho fosse concluído pelo usuário. Absolutamente não.
  2. Integrar o controle WebView em meu aplicativo. O uso do controle WebView do XAML permite inserir toda a navegação do fluxo de trabalho no contexto de meu aplicativo. Teoricamente, também posso ser notificado se o processo tiver sido concluído ouvindo o evento window.external.notify disparado pelo controle WebView. No entanto, na realidade, o evento é disparado apenas se a página da Web disparar o evento de notificação. Em meu caso, no entanto, a página do Dropbox onde o processo de autorização é concluído não dispara o evento. Paciência!
  3. Usar o WebAuthenticationBroker em meu aplicativo. À medida que fui me aprofundando no Tempo de Execução do Windows, acabei descobrindo a classe WebAuthenticationBroker. Parecia que ela poderia me ajudar a concluir o processo de autorização e, com algumas linhas de código, conseguir fazer toda a funcionalidade funcionar. Antes de me aprofundar pelo código, deixe-me explicar o WebAuthenticationBroker mais detalhadamente.

WebAuthenticationBroker

Em um mundo conectado por aplicativos, pedir as credenciais do usuário por meio de um mecanismo confiável e seguro é importante para obter o consentimento e a aprovação de um usuário para um aplicativo. Nenhum desenvolvedor quer criar um aplicativo que vaze credenciais de usuário ou que esteja sujeito a ataques furtivos para sequestro de informações de usuário. O Tempo de Execução do Windows inclui uma série de APIs e as tecnologias necessárias que permitem que um desenvolvedor busque as credenciais do usuário de uma maneira segura e confiável. O WebAuthenticationBroker é uma das ferramentas que permitem que os aplicativos da Windows Store usem protocolos de autenticação e de autorização baseados na Internet, como o OAuth e o OpenID. Mas como isso funciona em meu aplicativo de exemplo Dropbox? Veja como:

  • Faço a solicitação assíncrona inicial ao Dropbox, que retorna um token e um segredo de token para meu aplicativo. Essa solicitação inicial é feita por meio da função oAuthLoginAsync.
  • Quando a função oAuthLoginAsync retornar, em continuação da sequência, construo o URI onde o processo de autorização deve ser iniciado. Em meu exemplo, defini o URI inicial como uma cadeia de caracteres constante:
const std::wstring DropBoxAuthorizeURI = 
  L"https://www.dropbox.com/1/oauth/authorize?oauth_token=";
  • Em seguida, crio o URI de solicitação HTTP inserindo o token retornado pelo Dropbox.
  • Como uma etapa adicional, construo o parâmetro do URI de retorno de chamada chamando a função WebAuthenticationBroker::GetCurrent­ApplicationCallbackUri. Observe que não usei o parâmetro de URI de retorno de chamada em meu aplicativo da área de trabalho porque o parâmetro de retorno de chamada é opcional, e eu estava contando com o Internet Explorer para realizar a tarefa de autorização.
  • Agora minha cadeia de caracteres de solicitação está pronta e eu posso colocar minha solicitação. Em vez de usar a interface a classe http_client ou a interface IHttpWebRequest2 do C++ REST SDK para fazer chamadas de serviço Web, chamo a função WebAuthenticationBroker::AuthenticateAsync.
  • A função WebAuthenticationBroker::AuthenticateAsync aceita dois parâmetros: uma enumeração WebAuthenticationOptions e um URI. Uma instância sobrecarregada da mesma função aceita a enumeração WebAuthenticationOptions e dois URIs, um URI inicial onde o processo de autenticação é iniciado e um URI final onde o processo de autenticação termina.
  • Eu uso a primeira versão da função AuthenticateAsync e passo um valor None para a enumeração WebAuthenticationOptions. Para o URI, passo o URI que criei para minha solicitação da Web.
  • O WebAuthenticationBroker está entre meu aplicativo e o sistema. No ponto onde chamo AuthenticateAsync, ele cria uma caixa de diálogo modal, que é modal para meu aplicativo.
  • O agente anexa uma janela do host Web para a caixa de diálogo modal que criou.
  • Em seguida, o agente seleciona um processo de contêiner de aplicativo dedicado separado do contêiner de aplicativo no qual meu aplicativo está executando. Também limpara todos os dados persistidos do meu aplicativo.
  • Em seguida, o agente inicia o processo de autenticação nesse contêiner de aplicativo recém-selecionado e navega para o URI, conforme especificado na função AuthenticateAsync.
  • À medida que os usuários interagem com as páginas da Web, o agente continua verificando cada URL para o URI de retorno de chamada que foi especificado.
  • Quando uma correspondência é localizada, o host Web encerra a navegação e envia um sinal ao agente. O agente desativa a caixa de diálogo, limpa todos os cookies persistidos criados pelo host Web do contêiner do aplicativo e devolve os dados do protocolo ao aplicativo.

A Figura 3 ilustra a caixa de diálogo modal Web­AuthenticationBroker de meu aplicativo Dropbox de exemplo depois que o host Web navegou para o URI inicial. Como o Dropbox espera que os usuários entrem para que a página de autorização seja exibida, o host Web redireciona a navegação para a página de entrada do Dropbox.

The Sign-in Page of Dropbox as Displayed in the Modal Dialog
Figura 3 A página de entrada do Dropbox conforme exibida na caixa de diálogo modal

Depois de um usuário entrar no Dropbox, o host Web navega para o URI de autorização real. Isso é mostrado na Figura 4. Fica claro a partir da Figura 3 e da Figura 4 que a caixa de diálogo é sobreposta sobre a interface do usuário de meu aplicativo. A interface do usuário permanece consistente independentemente do aplicativo de origem chamar o método WebAuthenticationBroker::Authen­ticateAsync. Como toda a experiência permanece consistente, os usuários podem fornecer as informações de credenciais sem se preocupar com o manuseio das informações das credenciais pelos aplicativos e com o vazamento acidental dessas informações.

User Consent Being Asked for Application Authorization from Dropbox
Figura 4 Consentimento do usuário sendo pedido para autorização do aplicativo no Dropbox

Uma coisa importante que não mencionei é a necessidade de chamar a função WebAuthenticationBroker::AuthenticateAsync no thread da interface do usuário. Todas as solicitações da Web do C++ REST SDK são feitas em um thread de segundo plano, e eu não posso exibir a interface do usuário em um thread de segundo plano. Em vez disso, uso o dispatcher do sistema e chamo sua função membro, RunAsync, para exibir a interface do usuário modal, conforme mostrado na Figura 5.

Figura 5 Usando o dispatcher do sistema para exibir a interface do usuário modal

auto action = m_dispatcher->RunAsync(
  Windows::UI::Core::CoreDispatcherPriority::Normal,
  ref new Windows::UI::Core::DispatchedHandler([this]()
  {
    auto beginUri = ref new Uri(ref new String(m_authurl.c_str()));
    task<WebAuthenticationResult^> authTask(WebAuthenticationBroker::
      AuthenticateAsync(WebAuthenticationOptions::None, beginUri));
      authTask.then([this](WebAuthenticationResult^ result)
      {
        String^ statusString;
        switch(result->ResponseStatus)
        {
          case WebAuthenticationStatus::Success:
          {
            auto actionEnable = m_dispatcher->RunAsync(
              Windows::UI::Core::CoreDispatcherPriority::Normal,
              ref new Windows::UI::Core::DispatchedHandler([this]()
              {
                UploadFileBtn->IsEnabled = true;
              }));
          }
        }
      });
}));

Quando o processo de autorização é concluído, executo o dispatcher novamente para habilitar o botão "Upload File" (Carregar arquivo) em minha interface do usuário principal. Esse botão permanece em um estado desabilitado até que meus usuários tenham se autenticado e autorizado meu aplicativo a acessar o Dropbox.

Encadeando solicitações da Web assíncronas

Agora é fácil unir todos os elementos. Em todas as funções que não fazem interface com o Tempo de Execução do Windows, reutilizei o mesmo código de meu aplicativo da área de trabalho. Não há alterações importantes no código, com exceção desta: a decisão de usar o objeto StorageFile do WinRT versus um iostream do C++ na função UploadFileToDropboxAsync.

Ao escrever aplicativos para a Windows Store, há algumas limitações com as quais preciso conviver. Uma das limitações é a necessidade de usar objetos StorageFile do WinRT em vez de fluxos do C++ para ler e gravar dados em arquivos. Ao desenvolver um aplicativo da Windows Store e ao usar o C++ REST SDK, todas as operações relacionadas a arquivos esperam que o desenvolvedor passe um objeto StorageFile e não um objeto de fluxo do C++. Com essa alteração secundária, posso reutilizar todo o meu código padrão C++ que dá suporte ao código de autorização OAuth e Dropbox em meu aplicativo de exemplo da Windows Store.

Este é o fluxo de meu pseudocódigo (discutirei as funções individuais depois do pseudocódigo):

On clicking the SignIn Button
  Call oAuthLoginAsync function
    Then call WebAuthenticationBroker::AuthenticateAsync
    Then enable the "Upload File" button on my UI
On clicking the "Upload File" button
   Call the Windows::Storage::Pickers::FileOpenPicker::
     PickSingleFileAsync function
    Then call oAuthAcquireTokenAsync function
    Then call UploadFileToDropboxAsync function

No identificador do evento do botão SignInBtnClicked mostrado na Figura 6, eu primeiro executo uma validação simples de parâmetros para ter certeza de que valores de cadeias de caracteres não vazias são passados para os parâmetros ConsumerKey e ConsumerSecret, que passo para o Dropbox para autenticação. Em seguida, obtenho uma instância do objeto Dispatcher associado ao thread atual de CoreWindow e o armazeno em uma variável membro da classe MainPage. Um Dispatcher é responsável por processar as mensagens da janela e distribuir os eventos para o aplicativo. Em seguida, crio uma instância da classe OnlineIdAuthenticator. A classe OnlineIdAuthenticator contém funções auxiliares que permitem abrir uma caixa de diálogo modal do aplicativo e concluir o fluxo de trabalho de autorização seguro. Isso remove a necessidade de iniciar uma instância do navegador e alternar o foco do aplicativo para o navegador.

Figura 6 A função SignInBtnClicked

void MainPage::SignInBtnClicked(Platform::Object^ sender, 
  RoutedEventArgs^ e)
{
  if ((ConsumerKey->Text == nullptr) || 
    (ConsumerSecret->Text == nullptr))
  {
    using namespace Windows::UI::Popups;
    auto msgDlg = ref new MessageDialog(
      "Please check the input for the Consumer Key and/or Consumer Secret tokens");
    msgDlg->ShowAsync();
  }
  m_dispatcher =
     Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher;
  m_creds = std::make_shared<AppCredentials>();
  m_authenticator = ref new OnlineIdAuthenticator();
  consumerKey = ConsumerKey->Text->Data();
  consumerSecret = ConsumerSecret->Text->Data();
  ConsumerKey->Text = nullptr;
  ConsumerSecret->Text = nullptr;
  OAuthLoginAsync(m_creds).then([this]
  {          
    m_authurl = DropBoxAuthorizeURI;               
    m_authurl += 
      utility::conversions::to_string_t(this->m_creds->Token());
    m_authurl += L"&oauth_callback=";
    m_authurl += WebAuthenticationBroker::
      GetCurrentApplicationCallbackUri()->AbsoluteUri->Data();
    auto action = m_dispatcher->RunAsync(
      Windows::UI::Core::CoreDispatcherPriority::Normal,
      ref new Windows::UI::Core::DispatchedHandler([this]()
    {
      auto beginUri = ref new Uri(ref new String(m_authurl.c_str()));
      task<WebAuthenticationResult^>authTask(
        WebAuthenticationBroker::AuthenticateAsync(
        WebAuthenticationOptions::None, beginUri));
      authTask.then([this](WebAuthenticationResult^ result)
      {
        String^ statusString;
        switch(result->ResponseStatus)
        {
          case WebAuthenticationStatus::Success:
          {
            auto actionEnable = m_dispatcher->RunAsync(
              Windows::UI::Core::CoreDispatcherPriority::Normal,
              ref new Windows::UI::Core::DispatchedHandler([this]()
              {
                UploadFileBtn->IsEnabled = true;
              }));
          }
        }
      });
    }));
}

Em seguida, chamo a função OAuthLoginAsync, que executa a operação de logon no Dropbox. Quando a função assíncrona retorna, uso a função RunAsync do objeto Dispatcher para realizar marshaling do retorno da chamada para o thread da interface do usuário no thread de segundo plano de minha tarefa assíncrona. A função RunAsync utiliza dois parâmetros: um valor de prioridade e uma instância de DispatchedHandler. Defino o valor da propriedade como Normal e passo uma função lambda para a instância de DispatchedHandler. No corpo da lambda, chamo a função estática AuthenticateAsync da classe WebAuthenticationBroker, que então exibe a caixa de diálogo modal do aplicativo e ajuda a concluir a autorização segura.

Quando o fluxo de trabalho é concluído, a caixa de diálogo é desativada e a função retorna uma conclusão bem-sucedida ou quaisquer condições de erro encontradas. Em meu caso, apenas trato o tipo de retorno de WebAuthenticationStatus::Success e uso mais uma vez o objeto dispatcher para habilitar o botão UploadFile na interface do usuário do aplicativo. Como todas as funções que estou chamando são assíncronas por natureza, preciso usar o objeto dispatcher para realizar marshaling das chamadas para o thread da interface do usuário se eu quiser acessar qualquer elemento da interface do usuário.

A Figura 7 mostra o manipulador de eventos UploadFileBtnClicked. Não há muito código no próprio manipulador. Faço uma chamada para a função FileOpenPicker::PickSingleFileAsync que permite selecionar um único arquivo de texto por meio da interface do seletor. Em seguida, chamo a função OAuthAcquireTokenAsync, conforme mostrado na Figura 8, e, quando concluído com êxito, faço uma chamada para a função UploadFileToDropBoxAsync mostrada na Figura 9.

Figura 7 A função UploadFileBtnClicked

void MainPage::UploadFileBtnClicked(  Platform::Object^ sender, 
  RoutedEventArgs^ e)
{
  using namespace Windows::Storage::Pickers;
  using namespace Windows::Storage;
  auto picker = ref new FileOpenPicker();
  picker->SuggestedStartLocation = PickerLocationId::DocumentsLibrary;
  picker->FileTypeFilter->Append(".txt");
  task<StorageFile^> (picker->PickSingleFileAsync())
    .then([this](StorageFile^ selectedFile)
  {
    m_fileToUpload = selectedFile;
    OAuthAcquireTokenAsync(m_creds).then([this](){
      UploadFileToDropBoxAsync(m_creds);
    });
  });         
}

Figura 8 A função OAuthAcquireTokenAsync

task<void> MainPage::OAuthAcquireTokenAsync(
  std::shared_ptr<AppCredentials>& creds)
{
  uri url(DropBoxAccessTokenURI);
  std::shared_ptr<OAuth> oAuthObj = std::make_shared<OAuth>();
  auto signatureParams =
    oAuthObj->CreateOAuthSignedParameters(url.to_string(),
    L"GET",
    NULL,
    consumerKey,
    consumerSecret,
    creds->Token(),
    creds->TokenSecret()
    );
  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)
    {
      auto stream = response.body();                    
      container_buffer<std::string> inStringBuffer;
      return stream.read_to_end(inStringBuffer)
        .then([inStringBuffer](pplx::task<size_t> previousTask)
      {
        UNREFERENCED_PARAMETER(previousTask);
        const std::string &text = inStringBuffer.collection();
        // Convert the response text to a wide-character string.
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,
           wchar_t> utf16conv;
        std::wostringstream ss;
        ss << utf16conv.from_bytes(text.c_str()) << std::endl;
        OutputDebugString(ss.str().data());
        // Handle error cases.                   
        return pplx::task_from_result();
      });
    }
    // Perform actions here reading from the response stream.
    istream bodyStream = response.body();
    container_buffer<std::string> inStringBuffer;
    return bodyStream.read_to_end(inStringBuffer)
      .then([inStringBuffer, &creds](pplx::task<size_t> previousTask)
    {
      UNREFERENCED_PARAMETER(previousTask);
      const std::string &text = inStringBuffer.collection();
      // Convert the response text to a wide-character string.
      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->SetToken(token);
      creds->SetTokenSecret(tokenSecret);
    });
  });
}

Figura 9 A função UploadFileToDropBoxAsync

task<void> MainPage::UploadFileToDropBoxAsync(
  std::shared_ptr<AppCredentials>& 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(this->m_fileToUpload)
    .then([this, sb, url](pplx::task<basic_istream<unsigned char>> previousTask)
  {
    try
    {
      auto fileStream = previousTask.get();
      // Get the content length, 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([this, fileStream](pplx::task<http_response> previousTask)
      {
        fileStream.close();
        std::wostringstream ss;
        try
        {
          auto response = previousTask.get();
          auto body = response.body();                  
          // Log response success code.
          ss << L"Server returned status code "
          << response.status_code() << L"."
          << std::endl;
          OutputDebugString(ss.str().data());
          if (response.status_code() == web::http::status_codes::OK)
          {
            auto action = m_dispatcher->RunAsync(
              Windows::UI::Core::CoreDispatcherPriority::Normal,
              ref new Windows::UI::Core::DispatchedHandler([this]()
              {
                using namespace Windows::UI::Popups;
                auto msgDlg = ref new MessageDialog(
                  "File uploaded successfully to Dropbox");
                msgDlg->ShowAsync();
              }));
          }
        }
        catch (const http_exception& e)
        {
          ss << e.what() << std::endl;
          OutputDebugString(ss.str().data());
        }
      });           
    }                         
    catch (const std::system_error& e)
    {
      // Log any errors here.
      // Return an empty task.
      std::wostringstream ss;
      ss << e.what() << std::endl;
      OutputDebugString(ss.str().data());
      return pplx::task_from_result();
    }
  });
}

A função OAuthAcquireTokenAsync executa a ação para obter o token real associado à conta do Dropbox. Primeiro, crio a cadeia de caracteres de acesso necessária e os cabeçalhos da solicitação HTTP e chamo o serviço do Dropbox para executar a validação das credenciais. Essa solicitação HTTP é do tipo GET e a resposta é retornada como um fluxo de caracteres. Analiso o fluxo e divido o fluxo de caracteres para obter o token real e os valores secretos do token. Esses são então armazenados na instância da classe AppCredentials.

Depois de obter o token real e os valores secretos do token com êxito do Dropbox, está no hora de colocá-los em uso carregando um arquivo no Dropbox. Como é norma em qualquer acesso de ponto de extremidade da Web do Dropbox, eu primeiro crio a cadeia de caracteres de parâmetros e os cabeçalhos HTTP. Em seguida, chamo o ponto de extremidade do serviço do Dropbox associado aos arquivos que estão sendo carregados. Essa solicitação HTTP é do tipo PUT porque estou tentando colocar conteúdo no serviço. Antes de colocar conteúdo, também preciso informar o Dropbox sobre o tamanho do conteúdo. Isso é especificado pela configuração da propriedade content_length do método HTTP_request::­set_body para o tamanho do arquivo que está sendo carregado. Depois que o método PUT retorna com êxito, uso o objeto dispatcher para exibir uma mensagem de êxito para o usuário.

O Linux é o próximo

A integração do C++ REST SDK em aplicativos Windows 8 (para Windows Store e área de trabalho) é simples e direta. Adicione os benefícios de escrever código que possa ser compartilhando entre as duas plataformas, de usar linguagens de programação C++ modernas e o fato do código ser portável entre aplicativos Windows e não Windows e você tem um vencedor. Você pode parar de se preocupar com as complicações específicas às plataformas quando relacionadas a APIs de rede e, em vez disso, usar seu tempo para pensar nos recursos para os quais seu aplicativo deve dar suporte. Nesse exemplo simples, usei o C++ REST SDK para autenticar um usuário no Dropbox e, em seguida, carregar um arquivo para a nuvem do Dropbox. Para obter mais informações sobre a API Dropbox REST, consulte a documentação em bit.ly/10OdTD0. Em um próximo artigo, mostrarei como realizar essa mesma tarefa em um cliente Linux.

Sridhar Poduri é gerente de programas na equipe do Windows da Microsoft. Um desenvolvedor aficionado pelo C++ e autor do livro “Modern C++ and Windows Store Apps” (Sridhar Poduri, 2013), ele mantém um blog sobre o C++ e o Tempo de Execução do Windows em sridharpoduri.com.

Agradecemos aos seguintes especialistas técnicos da Microsoft pela revisão deste artigo: Niklas Gustaffson, Sana Mithani e Oggy Sobajic