備忘録

備忘録

C++でHTTP(S)でGET/POSTする(cpprestsdk の使い方)

Ⅰ. はじめに

.NET系 であれば WebClient や HttpClient が標準である為、
追加のライブラリ無しでHTTPをモダンかつ簡単に扱うことができます。

しかし、C++にはそのような物が標準ではありません。
ライブラリを探した結果、Microsoft社が作成しているC++ RESET SDK(cpprestsdk)にたどり着きました。

Ⅱ. なぜ「C++ RESET SDK(cpprestsdk)」を選んだのか

Ⅲ. インストール方法

※NuGetで配布されている物はダイナミックリンクライブラリのみ。
スタティックリンクライブラリが欲しい人はこちら

Install-Package cpprestsdk
sudo apt-get install libcpprest-dev
brew install cpprestsdk

その他は公式を参照して下さい。
https://github.com/Microsoft/cpprestsdk/wiki/Getting-Started-Tutorial#getting-the-c-rest-sdk

Ⅳ. GET(同期)

// #pragma comment(lib, "crypt32.lib")
// #pragma comment(lib, "bcrypt.lib")
// #pragma comment(lib, "winhttp.lib")
#include <cpprest/http_client.h>

int main()
{
  web::http::client::http_client client(L"http://example.com/");
  auto response = client.request(web::http::methods::GET).get();
  if (response.status_code() == web::http::status_codes::OK)
  {
    // レスポンスを文字列として取得後、標準出力する
    auto body = response.extract_string().get();
    std::wcout << body << std::endl;
  }
  return 0;
}

Ⅴ. GET(非同期)

#include <Windows.h>
#include <iostream>
#include <cpprest/http_client.h>

using namespace web;
using namespace web::http;
using namespace web::http::client;

pplx::task<void> Get()
{
  return pplx::create_task([]
  {
    // proxyあり
    // auto config = http_client_config();
    // config.set_proxy(web_proxy(utility::conversions::to_string_t("http://127.0.0.1:8080")));
    // http_client client(L"https://jsonplaceholder.typicode.com/posts/1", config);

    http_client client(L"https://jsonplaceholder.typicode.com/posts/1");
    return client.request(methods::GET);
  }).then([](http_response response)
  {
    if (response.status_code() == status_codes::OK)
    {
      // レスポンスを文字列として取得後、標準出力する
      // auto body = response.extract_string();
      // std::wcout << body.get().c_str() << std::endl;

      // レスポンスをJSONとして解析する
      return response.extract_json();
    }
  }).then([](json::value json)
  {
    // タイトルだけ取得する
    std::wcout << json[L"title"].as_string() << std::endl;
  });
}

int main()
{
  // コマンドプロンプトの文字コードをUTF-8に設定する
  SetConsoleOutputCP(CP_UTF8);

  try
  {
    Get().wait();
  }
  catch (const std::exception &e)
  {
    std::cout << "Error " << e.what() << std::endl;
  }

  return 0;
}
実行結果

f:id:kagasu:20171007190436p:plain

Ⅵ. POST(JSON)(非同期)

#include <Windows.h>
#include <iostream>
#include <cpprest/http_client.h>

using namespace web;
using namespace web::http;
using namespace web::http::client;

pplx::task<int> Post()
{
  return pplx::create_task([]
  {
    json::value postData;

    auto sex = utility::conversions::to_string_t("man");
    postData[L"user_info"][L"name"] = json::value::string(L"user001");
    postData[L"user_info"][L"sex"] = json::value::string(sex);
    postData[L"user_info"][L"age"] = json::value::number(20);

    // proxyあり
    // auto config = http_client_config();
    // config.set_proxy(web_proxy(utility::conversions::to_string_t("http://127.0.0.1:8080")));
    // http_client client(L"http://localhost/api", config);
    http_client client(L"http://localhost/api");
    return client.request(methods::POST, L"", postData.serialize(), L"application/json");
  }).then([](http_response response)
  {
    if (response.status_code() == status_codes::OK)
    {
      //auto body = response.extract_string();
      //std::wcout << body.get().c_str() << std::endl;
      //std::cout << response.extract_json() << std::endl;
      return response.extract_json();
    }
  }).then([](json::value json)
  {
    // リザルトコードを返す
    return json[L"result"].as_integer();
  });
}

int main()
{
  // コマンドプロンプトの文字コードをUTF-8に設定する
  SetConsoleOutputCP(CP_UTF8);

  try
  {
    auto result = Post().wait();
    std::cout << "Result = " << result << std::endl;
  }
  catch (const std::exception &e)
  {
    std::cout << "Error " << e.what() << std::endl;
  }

  return 0;
}
実行結果

f:id:kagasu:20171007190519p:plain

Ⅶ. POST(form-urlencoded)

http_client client(L"http://localhost/api");
client.request(methods::POST, L"", uri::encode_uri(L"name=田中太郎&age=20"), L"application/x-www-form-urlencoded");
実行結果

省略

その他

Ubuntuコンパイルする時
$ g++ a.cpp -std=c++14 -lcpprest -lboost_system -lssl -lcrypto