TL;DR:
I have some very simple PHP code utilizing cURL that makes single HTTP requests (in practice, to a Diaspora* pod, though that shouldn't be relevant to the question). The code takes note of any cookies returned by the web server and then manually sets those values to libcurl's CURLOPT_COOKIE
. However, in trying to hunt down a bug, I'm finding that when I use CURLOPT_COOKIEFILE
and CURLOPT_COOKIEJAR
, the values of the cookies in the cookie file are different than when I use CURLOPT_COOKIE
. Why is this the case? (See code below.)
PRIOR RESEARCH
I have already looked other questions such as this one that suggest various ways of manipulating libcurl's options to keep the same resource handle around and the cookies in memory, but this is not suitable to my application. I need to access the cookie values directly and notably not on a filesystem (to save them into a database, but again, this should not matter with regards to the question).
CODE
For completeness, here is a test case for code I am using:
<?php
// This function simply extracts the cookie set by a webserver by looking at the full HTTP source traffic.
function readCookie ($str) {
$m = array();
preg_match('/Set-Cookie: (.*?);/', $str, $m);
return (!empty($m[1])) ? $m[1] : false;
}
// This function does the same for the CSRF token required for login.
function parseAuthenticityToken ($str) {
$m = array();
preg_match('/content="(.*?)" name="csrf-token"/', $str, $m);
return (!empty($m[1])) ? $m[1] : false;
}
// Get first page, to find the CSRF token.
$ch = curl_init('https://diasp.org/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = curl_exec($ch);
curl_close($ch);
$csrf_token = parseAuthenticityToken($resp);
$params = array(
'user[username]' => 'my_username',
'user[password]' => 'my_password',
'authenticity_token' => $csrf_token
);
// Make POST request to the log in controller.
$ch = curl_init('https://diasp.org/users/sign_in');
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// In order to work, the COOKIEFILE/JAR options must be used. Why?
//curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/test_cookiejar');
//curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/test_cookiejar');
$resp = curl_exec($ch);
curl_close($resp);
$cookies = readCookie($resp);
// Even if the login is successful, this fails if and only if no COOKIEFILE/JAR is specified.
// Why?
$ch = curl_init('https://diasp.org/stream');
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// If I use COOKIEFILE here, the request works. What is this line doing that CURLOPT_COOKIE is not?
//curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/test_cookiejar');
$resp = curl_exec($ch);
curl_close($ch);
var_dump($resp);
SUMMARY
I am making very simple, step-by-step, procedural calls to a web server. These requests are being made one after the other, and the resulting output (of the entire HTTP conversation, including headers), is saved in a variable, which is then read and the values of the cookies are parsed from the Set-Cookie HTTP header lines. However, these values are never the same as the values that libcurl writes to the COOKIEFILE if those lines are uncommented.
What am I doing wrong with CURLOPT_COOKIE
or what am I not doing with it that the CURLOPT_COOKIEFILE
and CURLOPT_COOKIEJAR
options are doing? Is it encoded or decoded in some reversible way? Thanks in advance.