This is an example script from a larger application, but shows the general process of what I'm trying to do. If I have the following script:
<?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');
I get the following response (as viewed via 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
The problem is that Set-Cookie: test1
... exists 3 different times, therefore increasing the header size unnecessarily. (Again, this is a simplified example -
in reality, I'm dealing with ~10 duplicate cookies in the ~800-byte range.)
Is there anything I can write in place of the TODO
that would get rid of the header either completely or so it only shows once? i.e. the following is my end goal:
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
though the Set-Cookie: test1=third
could not exist too and that's fine, but Set-Cookie: test2=keep
needs to remain. When I try setcookie('test1', '', 1);
to delete the cookie, it adds an additional header to mark it as expired:
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
And if I try removing the header like:
if (!headers_sent()) {
foreach (headers_list() as $header) {
if (stripos($header, 'Set-Cookie: test1') !== false) {
header_remove('Set-Cookie');
}
}
}
it removes all Set-Cookie
headers when I only want test1
removed.
As you suggested in that last block of code, the headers_list()
function could be used to check what headers have been sent. Using that, the last values for each cookie could be stored in an associative array. The names and values can be extracted using explode()
(along with trim()
).
When multiple cookies with the same name have been detected, we can use the header_remove()
call like you had, but then set the cookies to the final values. See the example below, as well as this example phpfiddle.
if (!headers_sent()) {
$cookiesSet = []; //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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With