C++の応用 - HTTP

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動

概要

HTTP (Hypertext Transfer Protocol) は、Web上でデータを転送するためのプロトコルである。
クライアントサーバモデルに基づいており、テキストベースのリクエストレスポンス方式である。

HTTPの主な特徴を、以下に示す。

  • ステートレス
    各リクエストは独立して処理される。
  • メソッド
    GET、POST、PUT、DELETE等がある。
  • ヘッダ
    リクエストとレスポンスに関する追加情報を含む。
  • ステータスコード
    サーバからの応答状態を示す。
    例: 200 OK、 404 Not Found


C++でHTTP通信を実装する場合は、一般的には、libcurlライブラリやBoost.Beastライブラリ等を使用することが多い。


cURLライブラリ

cURLライブラリとは

その他の様々な通信方法を知りたい場合は、cURLの公式Webサイトからサンプルコードを閲覧することができる。

cURLライブラリのインストール

パッケージ管理システムからインストール
# RHEL
sudo dnf install libcurl-devel

# SUSE
sudo zypper install libcurl-devel


ソースコードからインストール

もし、別途インストールする必要がある場合、ソースコードからcurlをインストールする。

curlのビルドに必要なライブラリをインストールする。

# SUSE
sudo zypper install make cmake gcc perl libopenssl-devel libopenssl-1_1-devel libzstd-devel c-ares-devel libpsl-devel \
                    libssh-devel      # オプション : libSSHライブラリを使用する場合
                    libssh2-devel     # オプション : libSSH2ライブラリを使用する場合
                    libgnutls-devel   # オプション : GNU TLSライブラリを使用する場合
                    mbedtls-devel     # オプション : Mbed TLSライブラリを使用する場合
                    libnghttp2-devel  # オプション : NGHTTPライブラリを使用する場合
                    libheimdal-devel  # オプション : GSSを使用する場合


curlの公式Webサイト、または、curlのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。

tar xf curl-<バージョン>.tar.xz
cd curl-<バージョン>


curlをビルドおよびインストールする。

mkdir build && cd build

# Configureスクリプトを使用する場合
../configure --prefix=<curlのインストールディレクトリ> \
             --with-openssl \
             --with-gnutls    # オプション : GNUTLSを使用する場合
             --with-wolfssl   # オプション : WolfSSLを使用する場合

# CMakeを使用する場合
cmake .. -DCMAKE_BUILD_TYPE=Release                      \
         -DCMAKE_INSTALL_PREFIX=<CURLのインストールディレクトリ> \
         -DENABLE_ARES=ON       \  # C Aresを有効にする場合
         -DCURL_USE_GNUTLS=ON   \  # GNU TLSを有効にする場合
         -DCURL_USE_MBEDTLS=ON  \  # Mbed TLSを有効にする場合
         -DCURL_USE_WOLFSSL=ON  \  # Wolf SSLを有効にする場合
         -DUSE_NGHTTP2=ON       \  # NG Httpを有効にする場合
         -DCURL_USE_GSSAPI=ON      # GSS APIを有効にする場合

make -j $(nproc)
make install


HTTPヘッダの取得例

以下の例では、cURLライブラリを使用してHTTPリクエストを行い、HTTPヘッダのみを取得している。
もし、ステータスコードが200以外の場合は、エラーメッセージを出力している。

サンプルコードでは、以下に示すような手順を行っている。

  1. curl_easy_init関数を実行して、cURLハンドルを初期化する。
  2. curl_easy_setopt関数を実行して、リクエスト先のURLと各種オプションを設定する。
    • CURLOPT_URL
      リクエスト先のURLを指定する。
    • CURLOPT_NOBODY
      ボディを取得せずに、HTTPヘッダのみを取得するよう指示する。
    • CURLOPT_HEADER
      レスポンスヘッダを出力するかどうかを設定する。
    • CURLOPT_WRITEFUNCTION
      ボディデータを受信するコールバック関数を指定する。
      HTTPヘッダのみを取得する場合は、コールバック関数内で破棄する。
  3. curl_easy_performを実行して、HTTPリクエストを実行する。
  4. curl_easy_getinfoを実行して、レスポンスコードを取得する。
  5. curl_easy_cleanupを実行して、cURLハンドルを解放する。


 #include <iostream>
 #include <curl/curl.h>
 
 static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
 {
    // ボディデータを取得する場合はこのコールバック関数内で処理する
    return size * nmemb;
 }
 
 int main()
 {
    CURLcode res;
 
    CURL *curl = curl_easy_init();
    if (!curl) {
       std::cerr << "curl_easy_init() failed" << std::endl;
       return -1;
    }
 
    // URLを設定
    curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com");
 
    // HTTPヘッダのみを取得するオプション
    curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
    curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
 
    // コールバック関数を設定してボディデータを破棄
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
 
    // HTTPリクエストを実行
    res = curl_easy_perform(curl);
 
    if (res != CURLE_OK) {
       std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
    }
    else {
       // ステータスコードを取得
       long response_code = 0L;
       res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
       if (res == CURLE_OK) {
          if (response_code == 200) {
             std::cout << "Response code: " << response_code << std::endl;
          }
          else {
             std::cerr << "Error: Response code is " << response_code << std::endl;
          }
       }
       else {
          std::cerr << "curl_easy_getinfo() failed: " << curl_easy_strerror(res) << std::endl;
       }
    }
 
    // cURLのリソースを開放
    curl_easy_cleanup(curl);
 
    return 0;
 }