删除重复" Set-Cookie"来自PHP响应的标头

时间:2017-04-25 22:10:10

标签: php cookies http-headers setcookie response-headers

这是来自较大应用程序的示例脚本,但显示了我尝试执行的操作的一般过程。如果我有以下脚本:

<?php
ob_start();

setcookie('test1', 'first');
setcookie('test1', 'second');
setcookie('test1', 'third');
setcookie('test2', 'keep');

//TODO remove duplicate test1 from headers

ob_end_clean();
die('end test');

我收到以下回复(通过Fiddler查看):

HTTP/1.1 200 OK
Date: Tue, 25 Apr 2017 21:54:45 GMT
Server: Apache/2.4.17 (Win32) OpenSSL/1.0.2d PHP/5.5.30
X-Powered-By: PHP/5.5.30
Set-Cookie: test1=first
Set-Cookie: test1=second
Set-Cookie: test1=third
Set-Cookie: test2=keep
Content-Length: 8
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

end test

问题是Set-Cookie: test1 ...存在3个不同的时间,因此不必要地增加了标题大小。 (再次,这是一个简化的例子 -  实际上,我在~800字节范围内处理~10个重复的cookie。)

有什么我可以代替完全摆脱标题的TODO或者它只显示一次吗?,即以下是我的最终目标:< / p>

HTTP/1.1 200 OK
Date: Tue, 25 Apr 2017 21:54:45 GMT
Server: Apache/2.4.17 (Win32) OpenSSL/1.0.2d PHP/5.5.30
X-Powered-By: PHP/5.5.30
Set-Cookie: test1=third
Set-Cookie: test2=keep
Content-Length: 8
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

end test

虽然Set-Cookie: test1=third也不存在,但这很好,但Set-Cookie: test2=keep需要保留。当我尝试setcookie('test1', '', 1);删除Cookie时,会添加一个额外的标头以将其标记为已过期:

Set-Cookie: test1=first
Set-Cookie: test1=second
Set-Cookie: test1=third
Set-Cookie: test2=keep
Set-Cookie: test1=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0

如果我尝试删除标题,如:

if (!headers_sent()) {
    foreach (headers_list() as $header) {
        if (stripos($header, 'Set-Cookie: test1') !== false) {
            header_remove('Set-Cookie');
        }
    }
}

当我只想删除Set-Cookie时,它会删除所有test1标题。

2 个答案:

答案 0 :(得分:2)

正如您在最后一段代码中所建议的那样,headers_list()函数可用于检查已发送的标头。使用它,每个cookie的最后一个值可以存储在一个关联数组中。可以使用explode()(以及trim())提取名称和值。

当检测到多个具有相同名称的Cookie时,我们可以像您一样使用header_remove()调用,但随后将Cookie设置为最终值。请参阅下面的示例,以及this example phpfiddle

if (!headers_sent()) {
    $cookiesSet = array(); //associative array to store the last value for each cookie
    $rectifyCookies = false; //multiple values detected for same cookie name

    foreach (headers_list() as $header) {
        if (stripos($header, 'Set-Cookie:') !== false) {
            list($setCookie, $cookieValue) = explode(':', $header);
            list($cookieName, $cookieValue) = explode('=', trim($cookieValue));
            if (array_key_exists($cookieName, $cookiesSet)) {
                $rectifyCookies = true;
            }
            $cookiesSet[$cookieName] = $cookieValue;
        }
    }
    if ($rectifyCookies) {
        header_remove('Set-Cookie');
        foreach($cookiesSet as $cookieName => $cookieValue) {
            //might need to consider optional 3rd - 8th parameters 
            setcookie($cookieName, $cookieValue);
        }
    }
}

输出:

  

缓存控制 max-age = 0,无缓存,无存储,必须重新验证
  连接保持活力
  内容编码 gzip
  内容类型 text / html;字符集= UTF-8
  日期 2017年4月26日星期三15:31:33 GMT
   Expires Wed,11 Jan 1984 05:00:00 GMT
   Pragma no-cache
  服务器 nginx
   Set-Cookie test1 =第三个   测试2 =保持
  转移编码分块
  变化接受编码

答案 1 :(得分:0)

我不明白为什么你认为你向我们展示的cookie删除代码会删除test2的setcookie。

如果您的代码多次设置相同的Cookie,则需要更改代码,以便多次停止设置Cookie!其他任何事情都是一个草率的解决方法。