C++ REST SDK を使用したネットワークプログラミングの基本

環境構築と依存ライブラリのインストール

$ brew install cpprestsdk
$ brew install boost
$ brew install openssl

プロジェクトの作成

Xcodeを開き、File / New / Project... ウィザードの最初のページで macOS / Command Line Tool を選択し、 次に C++ 言語を選んでプロジェクト名を入力。 最後に保存先フォルダを指定して Create ボタンを押す。

プロジェクト設定

Header Search Paths に以下を追加: /usr/local/Cellar/cpprestsdk/2.10.1/include /usr/local/Cellar/boost/1.70.0/include /usr/local/opt/openssl/include Library Search Paths に以下を追加: /usr/local/Cellar/cpprestsdk/2.10.1/lib /usr/local/Cellar/boost/1.70.0/lib /usr/local/opt/openssl/lib Other Linker Flags に以下を追加: -lcpprest -lboost_system -lboost_thread-mt -lssl -lcrypto

サンプルコード 1: HTTP GET リクエスト

#include <cpprest/http_client.h>
#include <cpprest/filestream.h>

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

int main() {
    auto output = std::make_shared<ostream>();

    pplx::task<void> task = fstream::open_ostream(U("output.html")).then([=](ostream file) {
        *output = file;
        http_client client(U("https://example.com"));
        uri_builder builder(U("/search"));
        builder.append_query(U("q"), U("cpprestsdk example"));

        return client.request(methods::GET, builder.to_string()).then([=](http_response resp) {
            printf("Status code: %u\n", resp.status_code());
            return resp.body().read_to_end(output->streambuf());
        });
    }).then([=](size_t) {
        return output->close();
    });

    try {
        task.wait();
    } catch (const std::exception &e) {
        printf("Error: %s\n", e.what());
    }

    return 0;
}
このコードは https://example.com/search?q=cpprestsdk+example からデータを取得し、output.html に保存します。

JSON Placeholder API の利用

JSON Placeholder (https://jsonplaceholder.typicode.com/) はテスト用のREST APIサイトです。 以下はC++ REST SDKを使用してAPIを呼び出し、JSONデータを取得する例です。 - GET /posts/1 - POST /posts - PUT /posts/1 - DELETE /posts/1

サンプルコード 2: JSON操作

#include <cpprest/http_client.h>
#include <cpprest/json.h>

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

static void print_json(const json::value &data) {
    if (!data.is_null()) {
        int user_id = data.at(U("userId")).as_integer();
        int id = data.at(U("id")).as_integer();
        string_t title = data.at(U("title")).as_string();
        string_t body = data.at(U("body")).as_string();

        wcout << L"Post {user_id=" << user_id << L", id=" << id 
              << L", title=\"" << title << L"\", body=\"" << body << L"\"}\n";
    }
}

static void fetch_post() {
    http_client client(U("https://jsonplaceholder.typicode.com"));
    uri_builder builder(U("/posts/1"));

    client.request(methods::GET, builder.to_string())
          .then([](http_response resp) -> pplx::task<json::value> {
              if (resp.status_code() == status_codes::OK)
                  return resp.extract_json();
              return pplx::task_from_result(json::value());
          })
          .then([](pplx::task<json::value> prevTask) {
              try {
                  const json::value &v = prevTask.get();
                  print_json(v);
              } catch (const http_exception &e) {
                  printf("Error: %s\n", e.what());
              }
          })
          .wait();
}

static void create_post() {
    http_client client(U("https://jsonplaceholder.typicode.com"));
    json::value payload;
    payload[U("userId")] = json::value::number(101);
    payload[U("title")] = json::value::string(U("Test Title"));
    payload[U("body")] = json::value::string(U("Test Body"));

    client.request(methods::POST, U("/posts"), payload)
          .then([](http_response resp) -> pplx::task<string_t> {
              if (resp.status_code() == status_codes::Created)
                  return resp.extract_string();
              return pplx::task_from_result(string_t());
          })
          .then([](pplx::task<string_t> prevTask) {
              try {
                  const string_t &v = prevTask.get();
                  cout << v << endl;
              } catch (const http_exception &e) {
                  printf("Error: %s\n", e.what());
              }
          })
          .wait();
}

// 同様に更新や削除処理も実装可能です。
これらの関数はそれぞれ異なるHTTPメソッドを使って、REST APIとのやり取りを行います。

タグ: cpprestsdk Boost OpenSSL HTTP JSON

7月31日 21:57 投稿