PHPがCurlを使用して複数のHTTP要求を実行する場合、Cookie、DNSキャッシュ、SSLセッションなどの複数のリクエスト間で特定のデータを共有する場合があります。この時点で、 curl_share_init()および関連する関数を使用して共有を達成できます。ただし、多くの開発者は、機能を使用しようとする際に共通の問題に遭遇します。この記事では、この問題の原因と解決策を詳細に分析します。
まず、 curl_share_initを使用してCookieを共有する方法をすばやく確認しましょう。
$sh = curl_share_init();
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
$ch1 = curl_init('https://m66.net/login');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_COOKIEFILE, '');
curl_setopt($ch1, CURLOPT_SHARE, $sh);
// このリクエストが設定されると仮定します Cookie
$response1 = curl_exec($ch1);
$ch2 = curl_init('https://m66.net/profile');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_COOKIEFILE, '');
curl_setopt($ch2, CURLOPT_SHARE, $sh);
// これが最後に要求された設定をここに送信することを願っています Cookie
$response2 = curl_exec($ch2);
curl_close($ch1);
curl_close($ch2);
curl_share_close($sh);
コードのロジックから、 curl_share_setopt()のcurl_lock_data_cookieを介してCookieの共有を実現することを期待しています。しかし、多くの開発者は、2番目の要求が最初の要求によって返されたCookieに付属していないと報告しています。
共有Cookieを設定しますが、 Libcurlは設定されていない限り、デフォルトでCookieを自動的に保存または書き込みしません。
curlopt_cookiefile :既存のCookieファイルを読み取ります
curlopt_cookiejar :リクエスト後にクッキーファイルを書き込みます
'' (空の文字列)に設定できますが、メモリ内のCookie処理を有効にしますが、この方法はcurl_share_*と組み合わせると不安定になる場合があります。
PHPのCurl拡張は、 Libcurlライブラリを使用します。一部のプラットフォームまたはバージョンでは、 Curl_share_*の動作は、公式ドキュメントの説明、特にCookieが関与する部分とはわずかに異なる場合があります。 curl_lock_data_cookieは、低レベルのlibcurlで使用できるように設計されていますが、PHPがカプセル化された後のコールメソッドは一貫してサポートしていません。
Cookieには、パス(パス)およびドメイン(ドメイン)制限があります。要求されたURLドメイン名が異なる場合(サブドメイン名が異なる場合でも)、Cookieは送信されません。同様に、サーバーによって設定されたCookieが特定のパスに対してのみ有効で、次の要求されたパスが含まれていない場合、Cookieは自動的に添付されません。
明示的な管理のために一時的なCookieファイルを使用することは、最も簡単で信頼できる方法です。
$tmpCookieFile = tempnam(sys_get_temp_dir(), 'cookie');
$ch1 = curl_init('https://m66.net/login');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_COOKIEJAR, $tmpCookieFile);
curl_setopt($ch1, CURLOPT_COOKIEFILE, $tmpCookieFile);
$response1 = curl_exec($ch1);
$ch2 = curl_init('https://m66.net/profile');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_COOKIEJAR, $tmpCookieFile);
curl_setopt($ch2, CURLOPT_COOKIEFILE, $tmpCookieFile);
$response2 = curl_exec($ch2);
この方法は、 curl_share_*に依存せず、Cookieを保存およびリロードできることを保証し、ほとんどのPHPプロジェクトに適しています。
特定のキー値のみを選択するなど、より慎重にCookieを制御する必要がある場合は、 Curlopt_headerFunctionを介して応答ヘッダーをキャプチャし、 Curlopt_Cookieを使用して手動で設定できます。
$cookies = [];
$ch1 = curl_init('https://m66.net/login');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_HEADERFUNCTION, function($ch, $header) use (&$cookies) {
if (preg_match('/^Set-Cookie:\s*(.*?)=([^;]*)/i', $header, $matches)) {
$cookies[$matches[1]] = $matches[2];
}
return strlen($header);
});
curl_exec($ch1);
curl_close($ch1);
$cookieString = '';
foreach ($cookies as $k => $v) {
$cookieString .= "$k=$v; ";
}
$ch2 = curl_init('https://m66.net/profile');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_COOKIE, $cookieString);
$response2 = curl_exec($ch2);
curl_share_init()は、Cookieなどのデータを共有するメカニズムを提供しますが、PHPで使用する場合は特に注意してください。 Cookieの共有動作は、ドメイン名、パス、PHPカプセル化、Libcurl自体のバージョンなど、さまざまな要因の影響を受けます。複数のリクエスト間でCookieを共有したい場合は、最も安全な方法は、ファイルメソッドを使用してCookieを明示的に管理するか、 curl_share_initに依存する代わりにCookieを手動で抽出および設定することです。
その根本的な原則を理解することにより、「共有されているように見えるが実際には有効ではない」というtrapを避けて、安定したHTTPクライアントロジックをより効果的に構築できます。