【问题标题】:Any way to keep curl's cookies in memory and not on disk将 curl 的 cookie 保存在内存中而不是磁盘上的任何方法
【发布时间】:2010-12-01 22:45:13
【问题描述】:

我在 php 5.3.0 中做一些 cURL 工作。

我想知道是否有任何方法可以告诉 curl 句柄/对象将 cookie 保留在内存中(假设我对多个请求重用相同的句柄),或者以某种方式返回它们并让我将它们传回制作新手柄时。

有这种长期接受的方法可以让他们进入/退出请求:

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

但是我遇到了一些场景,我需要在同一个目录中运行多个脚本副本,并且它们会相互影响 cookie 文件。是的,我知道我可以使用 tempnam() 并确保每次运行都有自己的 cookie 文件,但这导致了我的第二个问题。

还有一个问题是在磁盘上有这些 cookie 文件。磁盘 I/O 很慢,我敢肯定这是一个瓶颈。我不想在脚本完成后清理 cookie 文件(如果它甚至以一种让我清理它的方式退出)。

有什么想法吗?还是事情就是这样?

【问题讨论】:

  • 老实说,我认为您在进行网络 I/O 时不必担心磁盘 I/O。

标签: php curl diskspace


【解决方案1】:

如果使用 Linux,您可以将它们设置为指向 /dev/shm 中的某个位置。这会将它们保存在内存中,并且您可以确保它们不会在重新启动后持续存在。

我不知何故认为 Curl 的清理处理了 cookie 的取消链接,但我可能弄错了。

【讨论】:

    【解决方案2】:

    不幸的是,我认为您不能使用 'php://memory' 作为输入和输出流。解决方法是自己解析标头。这可以很容易地完成。下面是一个页面示例,该页面发出两个请求并自己传递 cookie。

    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'];
    }
    ?>
    

    这将输出“你好!”第二个请求。

    【讨论】:

    • 请注意,如果您在一系列请求中多次解析 cookie,则可能必须在字符串中累积 cookie,可能会用新值覆盖旧值以用于重新出现的键。 (.. 实现 cookie 罐的滑坡开始了!)
    【解决方案3】:

    您可以使用CURLOPT_COOKIEJAR 选项,并将文件设置为Linux / MacOS X 的“/dev/null”或Windows 的“NULL”。这将阻止 cookie 写入磁盘,但只要您重复使用句柄并且不调用 curl_easy_cleanup(),它就会将它们保留在内存中。

    【讨论】:

    • 所以 cookie 在 curl_close() 被调用之前是有效的?你测试过这个吗?
    • 我在发布之前通读了 libcurl 源代码以验证这一点。
    • 我已经尝试过了,它似乎不起作用。在 Windows 和 *nix 中都没有。
    • 如果你能发布一个完整的工作实现就好了,我对此很感兴趣,但正如我之前所说的,它似乎不起作用。也许我错过了什么?
    • 如果你这样做,那么以 root 身份运行你的程序将擦除 /dev/null,从而使你的系统崩溃。 (github.com/oVirt/ovirt-engine-sdk/issues/34)
    【解决方案4】:

    只需将 CURLOPT_COOKIEFILE 设置为不存在的文件,通常空字符串是最佳选择。然后不要设置 CURLOPT_COOKIEJAR,这就是诀窍。这将阻止写入文件,但 cookie 将保留在内存中。我刚刚对此进行了测试,它可以正常工作(我的测试:将 http auth 数据发送到一个 URL,该 URL 将您重定向到对请求进行身份验证的登录 URL,然后将您重定向回带有 cookie 的原始 URL)。

    【讨论】:

    • 太棒了,这正是我想要的。我将CURLOPT_COOKIEFILE 设置为null 并避免设置CURLOPT_COOKIEJAR 选项,它起作用了!
    【解决方案5】:

    对我有用的是使用此设置:

    curl_setopt($ch, CURLOPT_HEADER, 1);
    

    然后解析结果。 this blog post 中的详细信息,我在其中找到了如何执行此操作。
    既然那是旧的,这里是gist replacing deprecated functions

    【讨论】:

      【解决方案6】:

      有,但完全不直观。

      curl_setopt($curl, CURLOPT_COOKIEFILE, "");
      

      更多详情请见my answer in the comments

      【讨论】:

      • 答案不太一样。 “到一个不存在的文件”。 Curl 通过设置执行各种操作的 cookie 文件来获取魔术字符串。您必须查看 curl 源代码或文档才能找到它。您实际上不应该将 curl 指向不存在的文件。他测试了它,发现它有效,但他不知道也没有解释原因。他的回答想要更新,因为它误导了为什么这样做。
      猜你喜欢
      • 2015-06-27
      • 1970-01-01
      • 2011-04-24
      • 2021-05-03
      • 2011-06-08
      • 2015-11-13
      • 2018-12-03
      • 1970-01-01
      • 2014-01-07
      相关资源
      最近更新 更多