概述
这是来自较大应用程序的示例脚本,但显示了我正在尝试执行的一般过程。 如果我有以下脚本:
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的东西,它可以完全摆脱标头,或者只显示一次? 即以下是我的最终目标:
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');
}
}
}
当我只想删除test1时,它将删除所有Set-Cookie标头。
您可以将标头存储在数组中吗? 例如 如果您有View类,则可以有一个(static?)方法SetCookie(),该方法会将键和值存储在关联数组中。 然后在发送最终标头时,只需遍历该关联数组并调用setcookie(),每个键只会被调用一次...
我希望! 理想的方式就是这样,但是到它到达我的脚本时,Set-Cookie: test1=...已经运行了多次,所以我可以在TODO处插入任何代码的地方
正如您在最后的代码块中所建议的那样,headers_list()函数可用于检查已发送了哪些头。 使用此方法,每个cookie的最后一个值可以存储在关联数组中。 可以使用explode()(以及trim())提取名称和值。
当检测到多个具有相同名称的cookie时,我们可以像以前一样使用header_remove()调用,然后将cookie设置为最终值。 请参见下面的示例以及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);
}
}
}
输出:
Cache-Control max-age=0, no-cache, no-store, must-revalidate
Connection keep-alive
Content-Encoding gzip
Content-Type text/html; charset=utf-8
Date Wed, 26 Apr 2017 15:31:33 GMT
Expires Wed, 11 Jan 1984 05:00:00 GMT
Pragma no-cache
Server nginx
Set-Cookie test1=third
test2=keep
Transfer-Encoding chunked
Vary Accept-Encoding
太棒了,这正是我想要的!
太好了我建议更改两件事以正确处理其他Cookie标头参数。 1)将两个爆炸的爆炸次数都限制为2,例如:explode(:, $header, 2) 2)使用header()函数而不是像header("Set-Cookie: {$cookieName}={$cookieValue}", false);那样的setcookie()这些更改将保持原始Set-Cookie的任何过期,Max-Age等参数标头。
@Stenerson好的,我可以将第三个参数添加到对explode()的调用中,但在阅读此答案后,看不出不使用setcookie()的很多原因(除非32位2038溢出问题影响您)... 。
请注意,可以将此代码放入函数中并在header-register_callback()中注册
我不明白您为什么认为您显示给我们的cookie删除代码会删除test2的setcookie。
如果您的代码多次设置相同的Cookie,则需要更改代码,以使其停止多次设置Cookie! 其他任何事情都是草率的解决方法。
您是说header_remove(Set-Cookie);?以其定义的方式(php.net/manual/en/function.header-remove.php),它删除了所有Set-Cookie标头。因此,无论cookie名称是什么,它都会清除它们。我正在使用一个似乎多次添加cookie的框架,因此我只是试图在返回响应之前清除它,而不会破坏内核。
h,当然!撇开错误的事实来解决问题,您可以将setcookie标头解析为name => value的数组,然后header_remove(Set-Cookie)然后再次遍历该数组。但这然后导致了一个稍微差一点的错误解决方案,该解决方案是首先填充数组,直到将数据编组后才调用setcookie()(但它仍然是错误的解决方案)
最后
以上就是重要天空为你收集整理的php headers cookies,从PHP响应中删除重复的“ Set-Cookie”标头的全部内容,希望文章能够帮你解决php headers cookies,从PHP响应中删除重复的“ Set-Cookie”标头所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复