Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
Allow overriding Session cookie params
Browse files Browse the repository at this point in the history
 * Build Cookie expiration time based on the request's server time
 * Allow overriding session cookie params via `session.session_params`
 * Initial integration testing
  • Loading branch information
simensen committed Feb 17, 2013
1 parent a985ee2 commit 38f211f
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 4 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ The following options can be used to configure stack/session:

* **session.default_locale** (optional): The default locale, defaults to `en`.

* **session.cookie_params** (optional): Override parameter values for the session cookie
as listed on [the PHP manual's session_get_cookie_params page](http://www.php.net/manual/en/function.session-get-cookie-params.php).
(allowed keys: `lifetime`, `path`, `domain`, `secure`, and `httponly`)

## Usage

The session middleware enables the `Session` object on the request. You can
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"require-dev": {
"silex/silex": "~1.0@dev",
"stack/stack": "~1.0@dev",
"stack/callable-http-kernel": "~1.0@dev",
"symfony/browser-kit": "~2.1"
},
"autoload": {
Expand Down
52 changes: 50 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions src/Stack/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,14 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ

if ($session && $session->isStarted()) {
$session->save();
$params = session_get_cookie_params();
$params = array_merge(
session_get_cookie_params(),
$this->container['session.cookie_params']
);
$cookie = new Cookie(
$session->getName(),
$session->getId(),
0 === $params['lifetime'] ? 0 : time() + $params['lifetime'],
0 === $params['lifetime'] ? 0 : $request->server->get('REQUEST_TIME') + $params['lifetime'],
$params['path'],
$params['domain'],
$params['secure'],
Expand Down
1 change: 1 addition & 0 deletions src/Stack/Session/ContainerConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ public function process(Pimple $container)
$container['session.storage.save_path'] = null;
$container['session.storage.options'] = [];
$container['session.default_locale'] = 'en';
$container['session.cookie_params'] = [];
}
}
155 changes: 155 additions & 0 deletions tests/integration/SessionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php

namespace integration;

use Pimple;
use Stack\CallableHttpKernel;
use Stack\Session;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;
use Symfony\Component\HttpKernel\Client;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class SessionTest extends \PHPUnit_Framework_TestCase
{
private $mockFileSessionStorage;

public function setUp()
{
$this->mockFileSessionStorage = new MockFileSessionStorage();
}

public function testDefaultSetsNoCookies()
{
$app = new CallableHttpKernel(function (Request $request) {
return new Response('test');
});

$client = new Client($app);

$client->request('GET', '/');

$this->assertEquals('test', $client->getResponse()->getContent());

$cookies = $client->getResponse()->headers->getCookies();
$this->assertCount(0, $cookies);
}

public function testDefaultSessionParams()
{
$app = new CallableHttpKernel(function (Request $request) {
$request->getSession()->set('some_session_var', 'is set');

return new Response('test');
});

$app = $this->sessionify($app);

$client = new Client($app);

$client->request('GET', '/');

$this->assertEquals('test', $client->getResponse()->getContent());

$cookies = $client->getResponse()->headers->getCookies();
$this->assertCount(1, $cookies);

$cookie = $cookies[0];
$this->assertEquals('', $cookie->getDomain());
$this->assertEquals('/', $cookie->getPath());
$this->assertEquals(false, $cookie->isSecure());
$this->assertEquals(false, $cookie->isHttpOnly());
$this->assertEquals(0, $cookie->getExpiresTime());

$bag = $this->mockFileSessionStorage->getBag('attributes');
$this->assertEquals('is set', $bag->get('some_session_var'));
}

/** @dataProvider provideOverrideSessionParams */
public function testOverrideSessionParams($expectedDomain, $expectedPath, $expectedSecure, $expectedHttponly, $expectedLifetime, $config)
{
$serverRequestTime = null;
$app = new CallableHttpKernel(function (Request $request) use (&$serverRequestTime) {
$serverRequestTime = $request->server->get('REQUEST_TIME');
$request->getSession()->set('some_session_var', 'is set');

return new Response('test');
});

$app = $this->sessionify($app, $config);

$client = new Client($app);

$client->request('GET', '/');

$this->assertEquals('test', $client->getResponse()->getContent());

$cookies = $client->getResponse()->headers->getCookies();
$this->assertCount(1, $cookies);

$cookie = $cookies[0];
$this->assertEquals($expectedDomain, $cookie->getDomain());
$this->assertEquals($expectedPath, $cookie->getPath());
$this->assertEquals($expectedSecure, $cookie->isSecure());
$this->assertEquals($expectedHttponly, $cookie->isHttpOnly());

if (0 === $cookie->getExpiresTime()) {
// Special case for a Cookie with a 0 (zero) expires time, we want
// to just compare directly against the expected lifetime with no
// time calculation.
$this->assertEquals($expectedLifetime, $cookie->getExpiresTime());
} else {
// In all other cases, we want to subtract the server request time
// from the expires time to see if it matches our expected lifetime.
$this->assertEquals($expectedLifetime, $cookie->getExpiresTime() - $serverRequestTime);
}

$bag = $this->mockFileSessionStorage->getBag('attributes');
$this->assertEquals('is set', $bag->get('some_session_var'));
}

public function provideOverrideSessionParams()
{
return [
['example.com', '/test-path', true, true, 300, ['session.cookie_params' => [
'lifetime' => 300,
'domain' => 'example.com',
'path' => '/test-path',
'secure' => true,
'httponly' => true,
]]],
['example.com', '/', false, false, 0, ['session.cookie_params' => [
'domain' => 'example.com',
]]],
['', '/test-path', false, false, 0, ['session.cookie_params' => [
'path' => '/test-path',
]]],
['', '/', true, false, 0, ['session.cookie_params' => [
'secure' => true,
]]],
['', '/', false, true, 0, ['session.cookie_params' => [
'httponly' => true,
]]],
['', '/', false, false, 300, ['session.cookie_params' => [
'lifetime' => 300,
]]],
['', '/', false, false, -300, ['session.cookie_params' => [
'lifetime' => -300,
]]],
];
}

private function sessionify(HttpKernelInterface $app, array $config = [])
{
$mockFileSessionStorage = $this->mockFileSessionStorage;

$config = array_merge([
'session.storage' => Pimple::share(function () use ($mockFileSessionStorage) {
return $mockFileSessionStorage;
}),
], $config);

return new Session($app, $config);
}
}

0 comments on commit 38f211f

Please sign in to comment.