C++

RESTful-Dienste für C++-Entwickler

Sridhar Poduri

In diesem Artikel werde ich zeigen, wie das C++-REST-SDK verwenden, um eine einfache Windows-basierten Client-Anwendung zu erstellen, die eine Datei zu Dropbox, zusammen mit einem C++-Standardklasse hochlädt, die OAuth unterstützt.

Die Welt der angeschlossenen Geräte bewegt sich zunehmend in eine heterogene Mischung aus nativen Anwendungen, Webanwendungen und Websites alle anschließen an eine Mischung aus Wolken - und nicht-Cloud-basierter Dienste.Diese apps teilen und Nutzen von Daten durch dieses Mischmasch von Geräten und Diensten und bieten reiche, immersive Erfahrungen für Endbenutzer. Diese Benutzer verwenden zunehmend apps installiert auf ihren persönlichen Geräten (Smartphones, Tablets, PCs und andere ähnlichen Vorrichtungen).Entwickler sind damit beauftragt, mit dem Erstellen von nahtloser Erfahrungen in jene apps zu erleichtern, teilen, organisieren und Anzeigen von Daten – und Freude-Benutzer.

Apps sind in einer Vielzahl von Programmiersprachen geschrieben.Einige, wie PHP, c# und Java, von Standard-Web-fähig und kann den Bedürfnissen der einige gängige Szenarien für den Austausch und Nutzung von Daten.In anderen Fällen könnte Fachbibliotheken genutzt werden, zum Ausführen von Server-seitige Datenverarbeitung, Verarbeitung und Analyse, und eine Antwort an die Clientanwendung zurück.

In seinem Vortrag, "Welcome to the Jungle" (bit.ly/uhfrzH), Herb Sutter beschreibt eindeutig die etablierten Bewegung zu elastisch, verteiltes computing als eine natürliche Entwicklung der gleichen Skala und Leistung Tendenzen, die haben getrieben Mehrkern- und heterogenen computing in den Mainstream.

C++ ist die bevorzugte Programmiersprache, wenn Cross-Plattform-Codeshare Flüge und Leistung Überlegungen zum Entwurf sind.Wenn es darum geht, cloud computing, aber bieten nicht C++ scheinbar auf ihr volles Potenzial.Einer der Hauptgründe für diesen offensichtlichen Fehler zitiert ist das Fehlen einer Cross-Plattform, leistungsfähige und effizient skalierbare Bibliothek, die einen C++-Entwickler vorhandenen C- und C++-Code nahtlos in die Cloud-Umgebung zu integrieren ermöglichen würde.

Das C++-REST-SDK (bit.ly/VI67I5) ist Microsofts erster Vorstoß in systemeigenen Code verschieben in der Cloud-Umgebung aktivieren.Es soll Entwickler Tools und APIs, die täglichen Probleme des Verschiebens von systemeigenen Codes an die Wolke zu lösen.Die erste Version ist eine Client-seitige, plattformübergreifende Bibliothek auf REST-Dienste.Das Ziel ist es, das C++-REST-SDK eine wirklich plattformunabhängige Bibliothek vornehmen, die das wahre Potenzial von systemeigenem Code in der Cloud nutzbar zu machen.Das C++-REST-SDK kann die Basis des Gebäudes mehr Fachbibliotheken z. B. zur Unterstützung von Windows-Azure-Services erstellen, und sie ermöglicht leichtes, Hochleistungs-Web-Services geschrieben werden, portable C++-Code ohne die Notwendigkeit für zusätzliche Frameworks oder Laufzeiten auf Cloud-basierte virtuelle Maschinen (VMs) bereitgestellt werden.

Warum das C++-REST-SDK?

Für den Zugriff auf Webdienste, bauen ein C++-Entwickler Abstraktionen über die C-Stil-APIs wie z. B. WinInet- oder WinHTTP unter Windows und ähnliche APIs auf anderen Plattformen.Solche Optionen gegeben, ist eine Frage, die für eine sofortige Antwort aufruft: Warum sollte ein Entwickler das C++-REST-SDK?

Das C++-REST-SDK entwickelt und von Grund auf mit modernen C++ geschrieben.Die Bibliothek schließt die folgenden Features ein:

  • Unterstützung für den Zugriff auf REST-basierte Dienste von systemeigenem Code auf Windows Vista, Windows 7, Windows 8, Windows Store apps und Linux durch die Bereitstellung von asynchroner Bindungen an HTTP, JSON, XML, URIs, und so weiter.
  • Ein Visual Studio -Erweiterung-SDK, die den Verbrauch des SDK in Windows Store apps ermöglicht.
  • Eine konsistente und leistungsstarke Programmiermodell für komponieren asynchrone Operationen basierend auf standard-C ++ 11 Funktionen.
  • Eine Implementierung des asynchronen Streams und Stream-Puffer, die zum Lesen und Schreiben von Datei/Gerät Streams verwendet werden können.

Die C++-REST-Client-Klassen

C++ REST baut auf der Prämisse der mit modernen C++ und asynchrone Programmiermuster.Ich habe für meine Experimente mit Dropbox die Http_client-Klasse, die Aufgabenklassen und der asynchronen Ströme-Klasse verwendet.Ich werde jeden Abschnitt erläutern.

Http_client Klasse wie der Name schon sagt, die Http_client-Klasse aus dem web::http-Namespace wird verwendet, um einrichten und Verwalten einer Verbindungs zu einem HTTP-Web-Dienst.Wenn Sie eine Instanz der Http_client und einen URI auf den Dienstendpunkt erstellen, kann die Objektinstanz verwendet werden, im Auftrag des Clients anzufordern.Asynchrone ist der C++-REST-Bibliothek erbaut, so dass Antworten von der Bibliothek als Aufgaben zurückgegeben werden.

Die Task-Klasse eine Aufgabe stellt eine Operation, die möglicherweise beendet werden kann, wenn die Funktion produzieren sagte Aufgabe ist bereits wieder zurückgekehrt.Nicht alle Aufgaben zum Abschluss ausgeführt, und es gibt keine Garantie in der Reihenfolge der Fertigstellung, entweder.Jedes Taskobjekt verfügt über eine Member-Funktion Is_done, die einen booleschen Wert zurückgibt.Wenn die Aufgabe vollständig ausgeführt wurde, gibt Is_done true zurück. Andernfalls gibt sie false zurück.Sobald eine Aufgabe vollständig ausgeführt wurde – wie von der Is_done-Member-Funktion zurückgegebene boolesche Wert angegeben — fordert die Aufgabe die Get-Funktion gibt den Wert aus der Aufgabe.Hüten Sie sich vor die Get-Funktion aufrufen, wenn die Is_done-Funktion false zurückgibt.Dadurch wird den Thread zu blockieren und Sinn und Zweck des Gebäudes asynchrone Muster im Code zu besiegen.

Statt ständig überprüfen für Is_done, ist es besser, die dann-Funktion zu verwenden.Es stützt sich auf eine Handlerfunktion auf die Aufgabe, ähnlich dem Versprechen in JavaScript-Erweiterungen für Windows Store apps anfügen.Es sollte leicht erkennbar für Entwickler verwenden die PPL-Aufgaben für die Programmierung von Windows-Runtime (WinRT) asynchrone Vorgänge verwendet.Die Handler-Funktion übergeben, die dann-Funktion sollte ein Argument Typ T oder Aufgabe <T> haben.Mithilfe des Arguments der Typ Aufgabe <T> verleiht einen zusätzlichen Vorteil: Es ist die einzige Möglichkeit zum Abfangen von Ausnahmen, die von der Task-Vorgang ausgelöst!

Da der Handler für die damalige Funktion aufgerufen wird, nur, nachdem der Vorgang abgeschlossen ist, rufen die Get-Funktion im Handler ist sicher und blockiert nicht den Thread.

Asynchronous-Streams The C++-REST-Bibliothek enthält eine Reihe von Hilfsklassen zum Lesen und Schreiben auf Objekte gekapselt als Streams und Stream-Puffer.Nach dem Muster und der Rangfolge in der C++-Standardbibliothek festgelegt, Streams und Puffer in C++ REST trennen die Sorge der Formatierung Daten für ein- und Ausgabe von der Sorge der schreiben und Lesen von Bytes oder Sammlungen von Bytes zu und von einigen zugrunde liegenden Medium wie einem TCP-Socket, eine Datenträgerdatei oder sogar einen Speicherpuffer.In gewisser Weise werden Ströme getrennt vom zugrunde liegenden Medium zum Lesen und Schreiben von Daten verwendet.Der große Unterschied mit Streams in C++ REST ist, dass sie Unterstützung von asynchronen Lesevorgang und Schreibvorgänge, im Gegensatz zu standard C++-Klassen, die blockieren.Wie die Gestaltung mit anderen C++ REST-Objekten ist zurück, die asynchronen Methoden in den Streamklassen eine Aufgabe <T> statt eines Werts.

Mit dieser Einführung in C++-REST ist es jetzt Zeit zum Nachdenken über die Dropbox-REST-API.In den Rest dieses Artikels werde ich erläutern, Zugriff auf die Dropbox-REST-API Verwendung von C++ REST zum Uploaden einer Datei auf dem lokalen Computer unter Windows in Dropbox-Ordner des Benutzers.

Die Dropbox-REST-API

Dropbox OAuth Version 1 verwendet, um alle Anforderungen an eine API zu authentifizieren (bit.ly/ZJLP4o) und erfordert, dass alle Anfragen über SSL erfolgen.Eine Internet-Suche für eine C++-Standardbibliothek, die Unterstützung von OAuth gibt nur die OAuth-Bibliothek, Liboauth, und es erfordert entweder Open­SSL (bit.ly/BpfcH) oder Mozilla Network Security Services (NSS) (mzl.la/abU77o).Ich wollte eine leichte, Cross-Plattform-Klasse, die OAuth, unterstützt, so dass ich zum Bau einer Dropbox-Authentifizierung unterstützt.

Für neugierige Leute, Brook Miles hat eine große Reihe von Stellen auf den Zugriff auf Twitter OAuth in C++ von Win32 (bit.ly/137Ms6y).Ich habe auf seine Grundideen gebaut aber umgestaltet Code zum Arbeiten mit den Dropbox-APIs verwenden die standard C++-Typen, die von C++ REST so weit wie möglich unterstützt.Darüber hinaus habe nicht ich beabsichtige, WinINet oder WinHTTP verwenden, um alle Webanforderungen durchzuführen, würde mich an die Windows-Plattform nur binden und zwingen Sie mich, eine C-Stil-API verwenden.

Jetzt werde ich erläutern, erstellen eine einfache C++-Klasse, die OAuth und einer Win32-Anwendung, die Verwendung von C++-REST, die Aufrufe an Dropbox und lädt eine Datei auf Dropbox unterstützt.In einem Follow-up-Artikel werde ich zeigen, wie Sie mit C++ REST aus einer Windows-Speicher-app und laden Sie Dateien auf Dropbox.

Bevor ich anfange, schreiben eine Anwendung, die Dropbox zugreifen kann, muss ich es mit Dropbox registrieren.Dies geschieht auf dem Dropbox Apps-Konsole-Portal (bit.ly/R14tjq).Ich habe mich für einen kostenlosen Dropbox-Account, in das Apps-Konsole-Portal angemeldet und erstellt eine neue app, indem Sie auf die Schaltfläche "Create app".

Der Prozess fordert Sie auf, wählen eine app-Namen, app-Typ und einen Berechtigungstyp.Ich trat "test" und wählte den app Typ Core (siehe Abbildung 1).Die anderen app-Typen sind Dropbox Chooser (nützlich für JavaScript-Entwickler) und Sync-API (am besten für iOS und Android-Entwickler).Schließlich entschied ich mich den Berechtigungstyp als vollständige Dropbox, wie dies gibt mir die Flexibilität von lesen, schreiben und synchronisieren in einen beliebigen Ordner auf Dropbox im Vergleich zu einem bestimmten Ordner, die von der "Sandbox" App Ordner Berechtigungstyp bereitgestellt wird.

Choices for Creating a Dropbox App
Abbildung 1-Möglichkeiten für die Schaffung einer Dropbox-App

Wenn Sie auf die Schaltfläche "Create app", Dropbox app erstellt und bietet Informationen, die erforderlich für den Zugriff, wie app-Schlüssel, app-Geheimnis und So weiter, siehe Abbildung 2.Ich habe Notiz davon, weil ich brauche sie programmgesteuerte Authentifizierung und Autorisierungsanforderungen mit OAuth durchführen.

Choosing Dropbox App DetailsAbbildung 2 Wahl Dropbox App Details

Eine einfache Cross-Plattform-C++-Klasse für OAuth

Jetzt für die eigentliche Aktion!Wie ich bereits sagte, wollte ich eine Cross-Plattform-Klasse schreiben, die auf Windows- und Linux verwendet werden könnten.Die aktuelle Version von C++-REST-SDK unterstützt nicht die HTTPS-Anforderungen von einem Linux-Rechner.Dies ist eine Enttäuschung, und ich habe gehört, dass vollständiger HTTPS-Unterstützung für Linux bald kommt.Die C++-Klasse, die ich hier besprechen sollte ohne große Änderungen auf Windows- und Linux funktionieren.Um OAuth-Authentifizierung für Dropbox zu unterstützen, musste ich die folgenden wichtigsten Anforderungen erfüllen (siehe die Dropbox-Website für volle Anforderungen):

  • Alle Anforderungen sollten über SSL erfolgen.Das bedeutet, nur HTTPS und HTTP verwenden.
  • OAuth erfordert diese Anforderung URIs und Parameter werden unterzeichnet mit HMAC-SHA1 oder RSA-SHA1 Verschlüsselung oder nur-Text, wenn die Anforderung über SSL erfolgt.

Im Sinne meiner Experimente ließ ich mich über die Verwendung von nur-Text-Signatur-Transport und Beantragung über HTTPS.Gebäude eine Verschlüsselung API, die auf Windows- und Linux arbeitet ist komplex und zeitaufwendig, und später eine detaillierte Untersuchung lohnt.

Einmal ich ließ auf die Anforderungen war es Zeit, die Klasse zu bauen.Ich erklärte einen High-Level-Namespace, bequem Authentifizierung genannt und eine Klasse innerhalb benannte oAuth.Auf Namespaceebene hatte ich ein paar const Zeichenfolgen für die URI-Endpunkte, die app-Schlüssel und app-Geheimnis für die app, die app-Registrierungsprozess und ein paar Hilfsmethoden, erklärt, wie in Abbildung 3.

Abbildung 3 Gebäude die oAuth-Klasse

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

Die gesamte OAuth-Protokoll-Unterstützung ist in der BuildSignedOAuthParameters-Methode der oAuth-Klasse implementiert. Diese Methode akzeptiert den Endpunkt-URI, den Typ der HTTP-Methode (GET, POST, PUT und so weiter), die app-Schlüssel, app Geheimnis, Anfrage-Token und token Geheimnis und baut eine Signatur, die über Dropbox mit jeder Anforderung gesendet werden soll. Dropbox versucht, genaue Signatur am Ende mit den Parametern übergeben mit der HTTPS-Anforderung zu bauen und die generierten Signaturen übereinstimmen. Wenn die Signaturen nicht übereinstimmen, wird einen HTTP-Fehlercode zurückgegeben.

Eine Signatur baut auf eine zufällige Zahl — eine Nonce im OAuth Sprachgebrauch genannt — einschließlich einen Zeitstempel für die Anforderung, die Version von OAuth-Protokoll unterstützt, den Signaturtyp und mehr. Die Methode liefert eine Liste aller erforderlichen Parameter, sortiert nach Namen und mit der Signatur-URL-codiert (siehe Abbildung 4).

Abbildung 4 Erstellen einer Signatur

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

Ich schrieb mit Unterstützung von OAuth aus dem Weg den Client-Code Access-Dateien auf Dropbox. Ich habe vier Methoden:

  1. oAuthLoginAsync: Führt die Anmeldung auf Dropbox mit dem app-Schlüssel und Geheimnis.
  2. AuthorizeDropBoxAccess: Internet Explorer startet und autorisiert app Zugriff auf Dropbox. Diese Methode ist spezifisch für Windows und Internet Explorer startet, unabhängig davon, ob er der Standardbrowser ist.
  3. oAuthAcquireTokenAsync: Führt die Aktion um das eigentliche Dropbox-Zugriffstoken zu erwerben.
  4. UploadFileToDropBoxAsync: Lädt eine Datei aus dem lokalen System zu Dropbox-Cloud-Speicher.

Jede dieser Operationen ist extrem einfach und nahtlos mit den C++-REST-Client-Klassen gemacht.

Der Clientcode

Geschrieben Client-Code wie moderne C++ mit asynchronen Aufgaben richten Sie gegen die Verwendung einer C-Stil-API mit? Es ist Zeit herauszufinden.

Mit einer C-Stil-API wie z. B. WinINet hätte ich zu der folgenden WinINet-API-Aufrufe zu meiner app zum laufen zu bringen:

  • Manuell erstellen des HTTP-Anfrage-Headers.
  • Rufen Sie InternetCrackUrl um die REST-Endpunkt-URL zu beheben.
  • Rufen Sie InternetOpen und erhalten Sie einen Handle für die Internet-Verbindung. In der Regel wird dies als eine HINTERNET-Instanz zurückgegeben.
  • Einmal ich ein gültiges Handle HINTERNET hatte, tätigen Sie einen Anruf auf Http­OpenRequest, die eine andere Instanz von HINTERNET zurückgibt.
  • Stellen Sie der nächsten Aufrufs von HttpAddRequestHeaders, die gibt einen booleschen Wert, der angibt, ob die Header-Informationen der HTTP-Anforderung erfolgreich hinzugefügt wurde.
  • Sobald ich erfolgreich alle, die die vorhergehenden Schritte mit der entsprechende Fehlerbehandlung eingeführt abgeschlossen, stellen Sie den Aufruf von HttpSendRequest, die die eigentliche Anfrage sendet.
  • Stellen Sie eine Antwort auf die vorherige Anforderung eingeht, ein weiterer Aufruf InternetReadFile den Antwortstream gelesen.

Bitte beachten Sie, dass alle früheren APIs APIs im C-Stil ohne Unterstützung für moderne C++ Programmierung Idiome wie freigegebenen Zeiger, Lambda-Ausdrücke und asynchrone Muster erbaut sind.

Jetzt für den eigentlichen Code mithilfe des C++-REST-SDK. Abbildung 5 zeigt die oAuthLoginAsync-Funktion, die führt den Login-Vorgang Dropbox und die UploadFileToDropBoxAsync-Funktion, die eine Datei aus dem lokalen System zu Dropbox hochlädt.

Abbildung 5 oAuthLoginAsync Funktion

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 der oAuthLoginAsync-Funktion erstellen Sie zuerst eine URI-Instanz aus einer Zeichenfolgendarstellung des Endpunkts Login URI. Als nächstes, erstellen Sie eine Instanz der Klasse oAuth und rufen Sie die Member-Funktion CreateOAuthSignedParameters, die eine Karte, die alle notwendigen Parameter von OAuth-Anforderung enthält aufbaut. Schließlich melden Sie die Header, durch Aufrufen der OAuthBuildSignedHeaders-Member-Funktion. Unterzeichnung der Header ist obligatorisch nach der OAuth-Spezifikation. Die HTTP-Kommunikation beginnt jetzt. Ich brauche nur erstellen Sie eine Instanz einer Http_client und übergeben sie die signierte Anforderungszeichenfolge. Dropbox verwenden die Request-String und Headerinformationen und Versuch, das gleiche zu bauen Zeichenfolge auf der Serverseite anfordern und es das match gegen was ich als Teil der HTTP-Anforderung zu senden. Wenn die Zeichenfolgen übereinstimmen, bekomme ich einen Erfolg-return-Code; Andernfalls erhalte ich eine Fehlermeldung.

Ich zunächst den Kommunikationsprozess erstellen eine Instanz der Klasse Http_client und rufen Sie dann die Anfrage-Member-Funktion. Die HTTP-Methode wie angeben Wenn die Anforderungsmethode Ausführung abgeschlossen ist, gibt es ein Http_response-Objekt, mit dem ich analysieren und das token und token-Geheimnis zu extrahieren, die in der App_credentials-Klasseninstanz gespeichert werden. Das Token sollte zusammen mit allen nachfolgenden API-Anforderungen an Dropbox gesendet werden.

Die UploadFileToDropBoxAsync-Funktion erscheint Abbildung 6. Es folgt einem ähnlichen Muster der oAuthLoginAsync-Funktion, bis ich die signierte OAuth-Header zu bauen. Sobald ich die Header-Informationen erstellen, erstellen Sie eine Aufgabe, die liest eine Datei aus dem lokalen Dateisystem in ein File_stream-Objekt und legt das File_stream-Objekt als HTTP-Request-Bodys. Ich kann dann erstellen Sie eine Instanz einer Klasse Http_client und legen Sie die Anfrage-Instanz, die den File_stream Inhalt als Text enthält, und platzieren Sie die PUT-Anforderung. Nach der Fertigstellung erhalte ich eine Aufgabe, die ein Http_response enthält, die für Erfolg oder Misserfolg analysiert werden kann. Es ist wirklich so einfach.

Abbildung 6 die UploadFileToDropBoxAsync-Funktion

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

Im Vergleich zu den mithilfe einer C-Stil-API für Web-Kommunikation oder geht den Weg der Unterstützung mit Plattform -­bestimmte APIs wie z. B. WinINet der Code mit modernen C++ geschrieben ist, knappe, lesbarer und elegant.In der Tat sind alle Low-Level Implementierungsdetails Weg von der öffentlichen Schnittstelle der Bibliothek abstrahiert.Das C++-REST-SDK baut auf das Versprechen der moderne C++ und wendet die gleichen Konstruktionsprinzipien für erholsame Kommunikation.Das Ergebnis ist eine extrem gut durchdachte und gemusterten Bibliothek mit modernen C++, das macht den Prozess des Aufbaus verbundenen apps einfach und nahtlos.

Weiter: Ein Windows-Speicher-App

In diesem Artikel habe ich untersucht, Gewusst wie: Erstellen eine einfachen Windows-basierten Client-Anwendung mit dem C++-REST-SDK, die eine Datei auf Dropbox hochlädt.Auf dem Weg habe ich auch diskutiert, erstellen eine standard C++-Klasse, die OAuth unterstützt.In einem Follow-up-Artikel zeige ich, wie Sie eine Windows-Speicher-app mit dem C++-REST-SDK zu erstellen.Bleiben Sie am Ball!

Sridhar Poduri ist Programmmanager im Windows-Team bei Microsoft. Ein C++-Fan und Autor des Buches "Moderne C++ und Windows Store Apps" (Sridhar Poduri, 2013), er Blogs regelmäßig über C++ und Windows Runtime bei sridharpoduri.com.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Artur Laksberg (Microsoft)
Artur Laksberg ist ein senior Development in C++ REST SDK-Team arbeiten.