35

I'm doing some cURL work in php 5.3.0.

I'm wondering if there is any way to tell the curl handle/object to keep the cookies in memory (assuming I'm reusing the same handle for multiple requests), or to somehow return them and let me pass them back when making a new handle.

Theres this long accepted method for getting them in/out of the request:

curl_setopt($ch, CURLOPT_COOKIEJAR, $filename); 
curl_setopt($ch, CURLOPT_COOKIEFILE, $filename);

But I'm hitting some scenarios where I need to be running multiple copies of a script out of the same directory, and they step on each others cookie files. Yes, I know I could use tempnam() and make sure each run has its own cookie file, but that leads me to my 2nd issue.

There is also the issue of having these cookie files on the disk at all. Disk I/O is slow and a bottle neck I'm sure. I dont want to have to deal with cleaning up the cookie file when the script is finished (if it even exits in a way that lets me clean it up).

Any ideas? Or is this just the way things are?

Uberfuzzy
  • 8,253
  • 11
  • 42
  • 50
  • 7
    Honestly, I don't think you'll need to be worrying about disk I/O when you're doing network I/O. – NSSec Sep 28 '09 at 09:18

6 Answers6

28

Unfortunately, I don't think you can use 'php://memory' as the input and output stream. The workaround is to parse the headers yourself. This can be done pretty easily. Here is an example of a page making two requests and passing the cookies yourself.

curl.php:

<?php

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://localhost/test.php?message=Hello!');
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($curl, CURLOPT_HEADER, true);  
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 

$data = curl_exec($curl);
curl_close($curl);

preg_match_all('|Set-Cookie: (.*);|U', $data, $matches);   
$cookies = implode('; ', $matches[1]);

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://localhost/test.php');
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($curl, CURLOPT_HEADER, true);  
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($curl, CURLOPT_COOKIE, $cookies);

$data = curl_exec($curl);
echo $data;

?>

test.php:

<?php
session_start();
if(isset($_SESSION['message'])) {
    echo $_SESSION['message'];
} else {
    echo 'No message in session';
}

if(isset($_GET['message'])) {
    $_SESSION['message'] = $_GET['message'];
}
?>

This will output 'Hello!' on the second request.

James Hall
  • 7,507
  • 2
  • 22
  • 15
  • 2
    Note that if you parse cookies out more than once in a sequence of requests, you may have to accumulate the cookies in your string, possibly overwriting older values with newer ones for re-occurring keys. (..and the slippery slope to implementing a cookie jar begins!) – adam smith May 02 '13 at 23:49
28

You can use the CURLOPT_COOKIEJAR option, and set the file to "/dev/null" for Linux / MacOS X or "NULL" for Windows. This will prevent the cookies from being written to disk, but it will keep them around in memory as long as you reuse the handle and don't call curl_easy_cleanup().

M at
  • 1,020
  • 1
  • 12
  • 26
Ben Combee
  • 16,831
  • 6
  • 41
  • 42
  • 1
    So the cookies will be valid until curl_close() is called? Have you tested this? – Alix Axel Nov 05 '09 at 22:11
  • 22
    I read through the libcurl source code to verify this before posting. – Ben Combee Nov 18 '09 at 02:19
  • 2
    I've tried it and it doesn't seem to work. Neither in Windows nor in *nix. – Alix Axel May 20 '10 at 17:20
  • 2
    It would be nice if you could post a fully working implementation, I've interest in this but as I said before it doesn't seem to work. Maybe I am missing something? – Alix Axel Jul 23 '10 at 12:27
  • I tested and "`NULL`" works and enough for both windows and linux. – Nabi K.A.Z. Jun 17 '19 at 17:55
  • 1
    If you do this, then running your program as root will erase /dev/null, leaving your system broken. (https://github.com/oVirt/ovirt-engine-sdk/issues/34) – Rich Mar 16 '21 at 16:22
12

Just set CURLOPT_COOKIEFILE to a file that doesn't exist, usually an empty string is the best option. Then DON'T set CURLOPT_COOKIEJAR, this is the trick. This will prevent a file from being written but the cookies will stay in memory. I just tested this and it works (my test: send http auth data to a URL that redirects you to a login URL that authenticates the request, then redirects you back to the original URL with a cookie).

mynameistechno
  • 3,526
  • 1
  • 37
  • 32
  • 3
    Brilliant, this was exactly what I was looking for. I set `CURLOPT_COOKIEFILE` to `null` and refrained from setting the `CURLOPT_COOKIEJAR` option, and it worked! – silkfire Nov 02 '14 at 18:45
4

There is but it's completely unintuitive.

curl_setopt($curl, CURLOPT_COOKIEFILE, "");

For more details please see my answer in the comments

Marian Nasry
  • 821
  • 9
  • 22
jgmjgm
  • 4,240
  • 1
  • 25
  • 18
  • It's not quite the same answer. "to a file that doesn't exist". Curl takes magic strings through setting the cookie file that do various things. You have to look at the curl source or documentation to find it. You shouldn't actually point curl to a file that doesn't exist. He tested it, found it worked but he doesn't know nor has explained why. His answer wants to be updated because it's misleading about why this works. – jgmjgm Apr 04 '18 at 09:49
2

If using Linux, you could set these to point somewhere within /dev/shm .. this will keep them in memory and you can be assured that they won't persist across re-boots.

I somehow thought that Curl's cleanup handled the unlinking of cookies, but I could be mistaken.

Tim Post
  • 33,371
  • 15
  • 110
  • 174
0

What works for me is using this setting:

curl_setopt($ch, CURLOPT_HEADER, 1);

And then parsing the result. Details in this blog post where I found out how to do this.
And since that is old, here is a gist replacing deprecated functions.

Marian Nasry
  • 821
  • 9
  • 22
eristoddle
  • 19
  • 1
  • 4