libcurl
C/C++向けの最も広く使用されるHTTPクライアントライブラリ。HTTPS、FTP、SMTP等多数のプロトコルサポート。curl コマンドラインツールの基盤技術として実績豊富。クロスプラットフォーム対応で、多くのアプリケーションとライブラリで採用。
GitHub概要
curl/curl
A command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features
トピックス
スター履歴
ライブラリ
libcurl
概要
libcurlは「C/C++向けの高性能マルチプロトコル転送ライブラリ」として開発された、世界で最も広く使用されているHTTPクライアントライブラリの一つです。cURLコマンドラインツールの中核として機能し、HTTP/HTTPS、FTP、SFTP、SMTP、IMAP、LDAP等30以上のプロトコルをサポート。シンプルで強力なCAPIを提供し、組み込みシステムからエンタープライズアプリケーションまで幅広い用途で採用。高い信頼性、豊富な機能、優れたパフォーマンスにより、様々なプログラミング言語のHTTPライブラリの基盤として利用されています。
詳細
libcurl 2025年版は20年以上の開発実績を持つ成熟したHTTPクライアントライブラリとして確固たる地位を維持しています。C言語ベースの設計により最高レベルのパフォーマンスを実現し、メモリ使用量の最適化と高速な処理速度を誇ります。HTTP/1.1、HTTP/2、HTTP/3の完全サポート、包括的なSSL/TLS対応、プロキシサーバー統合、Cookie管理、認証システム、カスタムヘッダー制御など、プロフェッショナル用途に必要な全機能を提供。クロスプラットフォーム対応により、組み込みシステムからクラウドインフラまで一貫した環境で利用可能です。
主な特徴
- マルチプロトコル対応: HTTP/HTTPS、FTP、SMTP等30以上のプロトコル
- 最新HTTP標準サポート: HTTP/3、HTTP/2、HTTP/1.1完全対応
- 高性能設計: C言語による最適化された実装とメモリ効率
- 包括的セキュリティ: SSL/TLS、証明書検証、暗号化通信
- 豊富な認証方式: Basic、Digest、NTLM、OAuth等の認証
- クロスプラットフォーム: Windows、Linux、macOS、組み込みシステム対応
メリット・デメリット
メリット
- C言語による高性能実装で最高レベルの処理速度と効率性を実現
- 30以上のプロトコル対応で多様な通信要件に単一ライブラリで対応
- 20年以上の開発実績による圧倒的な安定性と成熟度
- 組み込みシステムからエンタープライズまで幅広い環境で利用可能
- オープンソースでライセンス制約が少なく商用利用も自由
- 豊富なプログラミング言語バインディングによる高い汎用性
デメリット
- C言語APIのため他の高級言語ライブラリと比較して記述量が多い
- メモリ管理やエラーハンドリングを手動で行う必要がある
- コールバック関数ベースの設計で非同期処理が複雑になる場合がある
- 豊富な機能によりバイナリサイズが比較的大きくなる可能性
- デバッグやトラブルシューティングがより技術的な知識を要求
- 初心者には学習曲線が急になる場合がある
参考ページ
書き方の例
インストールと基本セットアップ
# Ubuntu/Debian でのインストール
sudo apt-get update
sudo apt-get install libcurl4-openssl-dev
# CentOS/RHEL でのインストール
sudo yum install libcurl-devel
# macOS (Homebrew) でのインストール
brew install curl
# Windows (vcpkg) でのインストール
vcpkg install curl
# ソースからビルド
curl -O https://curl.se/download/curl-8.x.x.tar.gz
tar -xzf curl-8.x.x.tar.gz
cd curl-8.x.x
./configure --with-ssl
make
sudo make install
# CMakeプロジェクトでの使用
find_package(CURL REQUIRED)
target_link_libraries(your_target ${CURL_LIBRARIES})
target_include_directories(your_target PRIVATE ${CURL_INCLUDE_DIRS})
基本的なHTTPリクエスト(GET/POST/PUT/DELETE)
#include <stdio.h>
#include <curl/curl.h>
// レスポンスデータを受け取るためのコールバック関数
struct MemoryStruct {
char *memory;
size_t size;
};
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
if (!ptr) {
printf("メモリ不足!realloc returned NULL\n");
return 0;
}
mem->memory = ptr;
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
// 基本的なGETリクエスト
int perform_get_request() {
CURL *curl;
CURLcode res;
struct MemoryStruct chunk;
chunk.memory = malloc(1);
chunk.size = 0;
curl = curl_easy_init();
if (curl) {
// URL設定
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/users");
// レスポンス受信コールバック
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
// ユーザーエージェント設定
curl_easy_setopt(curl, CURLOPT_USERAGENT, "MyApp/1.0 (libcurl)");
// SSL証明書検証を有効化
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
// リクエスト実行
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
} else {
printf("レスポンス: %s\n", chunk.memory);
// HTTPステータスコード取得
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
printf("HTTPステータス: %ld\n", response_code);
}
curl_easy_cleanup(curl);
}
if (chunk.memory) {
free(chunk.memory);
}
return 0;
}
// POSTリクエスト(JSON送信)
int perform_post_request() {
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
curl = curl_easy_init();
if (curl) {
// URL設定
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/users");
// POSTデータ
const char *json_data = "{\"name\":\"田中太郎\",\"email\":\"[email protected]\",\"age\":30}";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
// ヘッダー設定
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "Authorization: Bearer your-token");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// レスポンス受信設定
struct MemoryStruct chunk;
chunk.memory = malloc(1);
chunk.size = 0;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
// リクエスト実行
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "POST failed: %s\n", curl_easy_strerror(res));
} else {
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
printf("POST response (%ld): %s\n", response_code, chunk.memory);
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
if (chunk.memory) free(chunk.memory);
}
return 0;
}
// PUTリクエスト(データ更新)
int perform_put_request() {
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/users/123");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
const char *json_data = "{\"name\":\"田中次郎\",\"email\":\"[email protected]\"}";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "Authorization: Bearer your-token");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if (res == CURLE_OK) {
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
printf("PUT completed with status: %ld\n", response_code);
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return 0;
}
// DELETEリクエスト
int perform_delete_request() {
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/users/123");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
headers = curl_slist_append(headers, "Authorization: Bearer your-token");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if (res == CURLE_OK) {
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code == 204) {
printf("ユーザー削除完了\n");
}
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return 0;
}
int main() {
// libcurl初期化
curl_global_init(CURL_GLOBAL_DEFAULT);
perform_get_request();
perform_post_request();
perform_put_request();
perform_delete_request();
// libcurlクリーンアップ
curl_global_cleanup();
return 0;
}
高度な設定とカスタマイズ(認証、SSL、プロキシ等)
#include <curl/curl.h>
// Basic認証付きリクエスト
int authenticated_request() {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/private");
// Basic認証
curl_easy_setopt(curl, CURLOPT_USERNAME, "username");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
// または認証文字列を直接指定
// curl_easy_setopt(curl, CURLOPT_USERPWD, "username:password");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}
// カスタムヘッダーとタイムアウト設定
int custom_headers_and_timeout() {
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/data");
// カスタムヘッダー設定
headers = curl_slist_append(headers, "User-Agent: MyApp/1.0 (libcurl)");
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Accept-Language: ja-JP,en-US");
headers = curl_slist_append(headers, "X-API-Version: v2");
headers = curl_slist_append(headers, "X-Request-ID: req-12345");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// タイムアウト設定
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); // 接続タイムアウト10秒
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); // 全体タイムアウト30秒
// DNS解決タイムアウト
curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, 60L);
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return 0;
}
// SSL/TLS設定とクライアント証明書
int ssl_configuration() {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://secure-api.example.com/data");
// SSL証明書検証設定
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
// CA証明書バンドル指定
curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/ca-bundle.crt");
// クライアント証明書設定
curl_easy_setopt(curl, CURLOPT_SSLCERT, "/path/to/client.pem");
curl_easy_setopt(curl, CURLOPT_SSLKEY, "/path/to/client.key");
curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "certificate-password");
// SSL証明書タイプ指定
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
// SSL暗号化設定
curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, "HIGH:!aNULL:!MD5");
// 開発環境での証明書検証無効化(本番では非推奨)
// curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}
// プロキシサーバー設定
int proxy_configuration() {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/data");
// プロキシサーバー設定
curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example.com:8080");
// プロキシ認証
curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, "proxy_user");
curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, "proxy_pass");
curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
// プロキシタイプ指定
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
// HTTPSプロキシトンネリング
curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);
// SOCKSプロキシ例
// curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://proxy.example.com:1080");
// curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}
// Cookie管理
int cookie_management() {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/login");
// Cookieファイルからの読み込み
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookies.txt");
// Cookieファイルへの保存
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "/tmp/cookies.txt");
// インメモリでのCookie管理
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
// カスタムCookie設定
curl_easy_setopt(curl, CURLOPT_COOKIE, "session_id=abc123; user_pref=dark_mode");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}
エラーハンドリングとデバッグ機能
#include <curl/curl.h>
// 包括的なエラーハンドリング
int comprehensive_error_handling() {
CURL *curl;
CURLcode res;
char errbuf[CURL_ERROR_SIZE];
curl = curl_easy_init();
if (!curl) {
fprintf(stderr, "cURL初期化に失敗しました\n");
return 1;
}
// エラーバッファ設定
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
errbuf[0] = 0; // エラーバッファクリア
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/data");
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
size_t len = strlen(errbuf);
fprintf(stderr, "libcurl error (%d): ", res);
if (len) {
fprintf(stderr, "%s%s", errbuf,
((errbuf[len - 1] != '\n') ? "\n" : ""));
} else {
fprintf(stderr, "%s\n", curl_easy_strerror(res));
}
// エラータイプ別処理
switch (res) {
case CURLE_COULDNT_CONNECT:
fprintf(stderr, "接続エラー: サーバーに接続できません\n");
break;
case CURLE_OPERATION_TIMEDOUT:
fprintf(stderr, "タイムアウトエラー: リクエストがタイムアウトしました\n");
break;
case CURLE_SSL_CONNECT_ERROR:
fprintf(stderr, "SSL接続エラー: SSL/TLS接続に失敗しました\n");
break;
case CURLE_HTTP_RETURNED_ERROR:
fprintf(stderr, "HTTPエラー: サーバーがエラーを返しました\n");
break;
default:
fprintf(stderr, "その他のエラー: %s\n", curl_easy_strerror(res));
break;
}
} else {
// 成功時の詳細情報取得
long response_code;
double total_time, connect_time, download_time;
char *content_type = NULL;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time);
curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &connect_time);
curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &download_time);
curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type);
printf("=== リクエスト成功 ===\n");
printf("HTTPステータス: %ld\n", response_code);
printf("総実行時間: %.3f秒\n", total_time);
printf("接続時間: %.3f秒\n", connect_time);
printf("ダウンロード開始時間: %.3f秒\n", download_time);
printf("コンテンツタイプ: %s\n", content_type ? content_type : "unknown");
// HTTPステータスコード別処理
if (response_code >= 200 && response_code < 300) {
printf("成功: リクエストが正常に処理されました\n");
} else if (response_code >= 400 && response_code < 500) {
fprintf(stderr, "クライアントエラー (%ld): リクエストに問題があります\n", response_code);
} else if (response_code >= 500) {
fprintf(stderr, "サーバーエラー (%ld): サーバー側で問題が発生しています\n", response_code);
}
}
curl_easy_cleanup(curl);
return (res == CURLE_OK) ? 0 : 1;
}
// デバッグ機能付きリクエスト
static int debug_callback(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr)
{
const char *text;
(void)handle; // 未使用パラメータ警告抑制
(void)userptr;
switch (type) {
case CURLINFO_TEXT:
text = "== Info";
break;
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
case CURLINFO_DATA_OUT:
text = "=> Send data";
break;
case CURLINFO_SSL_DATA_OUT:
text = "=> Send SSL data";
break;
case CURLINFO_HEADER_IN:
text = "< Recv header";
break;
case CURLINFO_DATA_IN:
text = "< Recv data";
break;
case CURLINFO_SSL_DATA_IN:
text = "< Recv SSL data";
break;
default:
return 0;
}
printf("%s: %.*s", text, (int)size, data);
return 0;
}
int debug_enabled_request() {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/debug");
// デバッグ機能有効化
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debug_callback);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// プログレス情報表示
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "Debug request failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
return 0;
}
// リトライ機能付きリクエスト
int request_with_retry(const char *url, int max_retries) {
CURL *curl;
CURLcode res;
int attempt;
curl = curl_easy_init();
if (!curl) {
return -1;
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
for (attempt = 0; attempt <= max_retries; attempt++) {
printf("試行 %d/%d: %s\n", attempt + 1, max_retries + 1, url);
res = curl_easy_perform(curl);
if (res == CURLE_OK) {
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code == 200) {
printf("成功: リクエストが完了しました\n");
break;
} else if (response_code >= 500 && attempt < max_retries) {
printf("サーバーエラー (%ld): %d秒後に再試行します\n", response_code, (attempt + 1) * 2);
sleep((attempt + 1) * 2); // 指数バックオフ
} else {
printf("HTTPエラー (%ld): 再試行を中断します\n", response_code);
break;
}
} else if (attempt < max_retries) {
printf("接続エラー (%s): %d秒後に再試行します\n", curl_easy_strerror(res), (attempt + 1) * 2);
sleep((attempt + 1) * 2);
} else {
printf("最大試行回数に達しました: %s\n", curl_easy_strerror(res));
}
}
curl_easy_cleanup(curl);
return (res == CURLE_OK) ? 0 : -1;
}
マルチハンドルによる並行処理
#include <curl/curl.h>
// 複数URLの並行取得
struct url_data {
char *url;
char *data;
size_t size;
};
int parallel_requests() {
CURLM *multi_handle;
CURLMcode mc;
int still_running = 1;
int msgs_left;
CURLMsg *msg;
const char *urls[] = {
"https://api.example.com/users",
"https://api.example.com/posts",
"https://api.example.com/comments",
NULL
};
struct url_data url_data[3];
CURL *curl_handles[3];
// マルチハンドル初期化
multi_handle = curl_multi_init();
// 各URLに対してハンドル作成
for (int i = 0; urls[i]; i++) {
curl_handles[i] = curl_easy_init();
url_data[i].url = (char*)urls[i];
url_data[i].data = malloc(1);
url_data[i].size = 0;
curl_easy_setopt(curl_handles[i], CURLOPT_URL, urls[i]);
curl_easy_setopt(curl_handles[i], CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl_handles[i], CURLOPT_WRITEDATA, &url_data[i]);
curl_easy_setopt(curl_handles[i], CURLOPT_PRIVATE, &url_data[i]);
// マルチハンドルに追加
curl_multi_add_handle(multi_handle, curl_handles[i]);
}
// 並行実行開始
curl_multi_perform(multi_handle, &still_running);
// 処理完了まで待機
while (still_running) {
fd_set fdread, fdwrite, fdexcep;
int maxfd = -1;
long curl_timeo = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
// タイムアウト取得
curl_multi_timeout(multi_handle, &curl_timeo);
if (curl_timeo < 0)
curl_timeo = 1000;
// ファイルディスクリプタ取得
mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
if (mc != CURLM_OK) {
fprintf(stderr, "curl_multi_fdset failed: %s\n", curl_multi_strerror(mc));
break;
}
if (maxfd == -1) {
usleep(100000); // 100ms待機
} else {
struct timeval timeout;
timeout.tv_sec = curl_timeo / 1000;
timeout.tv_usec = (curl_timeo % 1000) * 1000;
int rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
if (rc < 0) {
perror("select");
break;
}
}
curl_multi_perform(multi_handle, &still_running);
}
// 結果処理
while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
if (msg->msg == CURLMSG_DONE) {
CURL *easy_handle = msg->easy_handle;
CURLcode result = msg->data.result;
struct url_data *data;
curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, &data);
if (result == CURLE_OK) {
long response_code;
curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &response_code);
printf("URL: %s (Status: %ld)\n", data->url, response_code);
printf("Data: %.100s...\n", data->data); // 最初の100文字表示
} else {
fprintf(stderr, "Error for %s: %s\n", data->url, curl_easy_strerror(result));
}
curl_multi_remove_handle(multi_handle, easy_handle);
curl_easy_cleanup(easy_handle);
}
}
// クリーンアップ
curl_multi_cleanup(multi_handle);
for (int i = 0; urls[i]; i++) {
if (url_data[i].data) {
free(url_data[i].data);
}
}
return 0;
}
int main() {
curl_global_init(CURL_GLOBAL_DEFAULT);
comprehensive_error_handling();
debug_enabled_request();
request_with_retry("https://api.example.com/test", 3);
parallel_requests();
curl_global_cleanup();
return 0;
}
ファイルアップロード・ダウンロード機能
#include <curl/curl.h>
// ファイルアップロード
int upload_file(const char *url, const char *file_path) {
CURL *curl;
CURLcode res;
FILE *file;
curl_mime *mime;
curl_mimepart *part;
curl = curl_easy_init();
if (!curl) {
return -1;
}
file = fopen(file_path, "rb");
if (!file) {
curl_easy_cleanup(curl);
return -1;
}
// MIME形式でファイルアップロード
mime = curl_mime_init(curl);
part = curl_mime_addpart(mime);
curl_mime_name(part, "file");
curl_mime_filedata(part, file_path);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
res = curl_easy_perform(curl);
fclose(file);
curl_mime_free(mime);
curl_easy_cleanup(curl);
return (res == CURLE_OK) ? 0 : -1;
}
// ファイルダウンロード
static size_t write_file_callback(void *contents, size_t size, size_t nmemb, FILE *stream) {
return fwrite(contents, size, nmemb, stream);
}
int download_file(const char *url, const char *output_path) {
CURL *curl;
CURLcode res;
FILE *fp;
curl = curl_easy_init();
if (!curl) {
return -1;
}
fp = fopen(output_path, "wb");
if (!fp) {
curl_easy_cleanup(curl);
return -1;
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
fclose(fp);
curl_easy_cleanup(curl);
return (res == CURLE_OK) ? 0 : -1;
}