Skip to content

Commit

Permalink
feature #20644 [HttpFoundation] Compute cookie max-age attribute (ro0NL)
Browse files Browse the repository at this point in the history
This PR was merged into the 3.3-dev branch.

Discussion
----------

[HttpFoundation] Compute cookie max-age attribute

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | comma-separated list of tickets fixed by the PR, if any
| License       | MIT
| Doc PR        | reference to the documentation PR, if any

See https://wiki.php.net/rfc/cookie_max-age, PHP sends it since 5.5.

~~The date format actually differs now from PHP (`Saturday` instead of `Sat`). But it really doesnt matter much imo, using the constant seems more reliable to me and max-age overrules anyway ;)~~

Relates to #20569

Commits
-------

8c28317 [HttpFoundation] Compute cookie max-age attribute
  • Loading branch information
fabpot committed Dec 15, 2016
2 parents b806ae0 + 8c28317 commit 9f95654
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 13 deletions.
14 changes: 12 additions & 2 deletions src/Symfony/Component/HttpFoundation/Cookie.php
Expand Up @@ -94,12 +94,12 @@ public function __toString()
$str = urlencode($this->getName()).'=';

if ('' === (string) $this->getValue()) {
$str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001);
$str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001';
} else {
$str .= urlencode($this->getValue());

if ($this->getExpiresTime() !== 0) {
$str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime());
$str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; max-age='.$this->getMaxAge();
}
}

Expand Down Expand Up @@ -166,6 +166,16 @@ public function getExpiresTime()
return $this->expire;
}

/**
* Gets the max-age attribute.
*
* @return int
*/
public function getMaxAge()
{
return 0 !== $this->expire ? $this->expire - time() : 0;
}

/**
* Gets the path on the server in which the cookie will be available on.
*
Expand Down
34 changes: 25 additions & 9 deletions src/Symfony/Component/HttpFoundation/Tests/CookieTest.php
Expand Up @@ -72,9 +72,13 @@ public function testGetPath()

public function testGetExpiresTime()
{
$cookie = new Cookie('foo', 'bar', 3600);
$cookie = new Cookie('foo', 'bar');

$this->assertEquals(0, $cookie->getExpiresTime(), '->getExpiresTime() returns the default expire date');

$cookie = new Cookie('foo', 'bar', $expire = time() + 3600);

$this->assertEquals(3600, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
$this->assertEquals($expire, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
}

public function testConstructorWithDateTime()
Expand Down Expand Up @@ -107,21 +111,21 @@ public function testGetExpiresTimeWithStringValue()

public function testGetDomain()
{
$cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com');
$cookie = new Cookie('foo', 'bar', 0, '/', '.myfoodomain.com');

$this->assertEquals('.myfoodomain.com', $cookie->getDomain(), '->getDomain() returns the domain name on which the cookie is valid');
}

public function testIsSecure()
{
$cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com', true);
$cookie = new Cookie('foo', 'bar', 0, '/', '.myfoodomain.com', true);

$this->assertTrue($cookie->isSecure(), '->isSecure() returns whether the cookie is transmitted over HTTPS');
}

public function testIsHttpOnly()
{
$cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com', false, true);
$cookie = new Cookie('foo', 'bar', 0, '/', '.myfoodomain.com', false, true);

$this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns whether the cookie is only transmitted over HTTP');
}
Expand All @@ -142,14 +146,14 @@ public function testCookieIsCleared()

public function testToString()
{
$cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
$this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', $cookie->__toString(), '->__toString() returns string representation of the cookie');
$cookie = new Cookie('foo', 'bar', $expire = strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
$this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; max-age='.($expire - time()).'; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie');

$cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com');
$this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; path=/admin/; domain=.myfoodomain.com; httponly', $cookie->__toString(), '->__toString() returns string representation of a cleared cookie if value is NULL');
$this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', $expire = time() - 31536001).'; max-age='.($expire - time()).'; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL');

$cookie = new Cookie('foo', 'bar', 0, '/', '');
$this->assertEquals('foo=bar; path=/; httponly', $cookie->__toString());
$this->assertEquals('foo=bar; path=/; httponly', (string) $cookie);
}

public function testRawCookie()
Expand All @@ -160,4 +164,16 @@ public function testRawCookie()
$cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com', false, true, true);
$this->assertTrue($cookie->isRaw());
}

public function testGetMaxAge()
{
$cookie = new Cookie('foo', 'bar');
$this->assertEquals(0, $cookie->getMaxAge());

$cookie = new Cookie('foo', 'bar', $expire = time() + 100);
$this->assertEquals($expire - time(), $cookie->getMaxAge());

$cookie = new Cookie('foo', 'bar', $expire = time() - 100);
$this->assertEquals($expire - time(), $cookie->getMaxAge());
}
}
Expand Up @@ -128,7 +128,7 @@ public function testToStringIncludesCookieHeaders()

$bag->clearCookie('foo');

$this->assertRegExp('#^Set-Cookie: foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; path=/; httponly#m', $bag->__toString());
$this->assertRegExp('#^Set-Cookie: foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001; path=/; httponly#m', $bag->__toString());
}

public function testClearCookieSecureNotHttpOnly()
Expand All @@ -137,7 +137,7 @@ public function testClearCookieSecureNotHttpOnly()

$bag->clearCookie('foo', '/', null, true, false);

$this->assertRegExp('#^Set-Cookie: foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; path=/; secure#m', $bag->__toString());
$this->assertRegExp('#^Set-Cookie: foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001; path=/; secure#m', $bag->__toString());
}

public function testReplace()
Expand Down

0 comments on commit 9f95654

Please sign in to comment.