merged branch schmittjoh/httpUtilFixes (PR #1739)

Commits
-------

eae6a77 fixed wrong case
d0a175b fixes #1659
f300ede fixes several bugs
a4f05ac added some tests

Discussion
----------

Http util fixes

Fixes several bugs in the http utils.

Please don't add anymore features without sufficient tests. Especially for the Security\Http namespace, regressions are very likely otherwise.

---------------------------------------------------------------------------

by fabpot at 2011/07/19 22:37:26 -0700

Tests do not pass for me:

    There were 2 errors:

    1) Symfony\Bundle\SecurityBundle\Tests\Functional\LocalizedRoutesAsPathTest::testLoginLogoutProcedure with data set #0 ('en')
    InvalidArgumentException: The current node list is empty.

    .../src/Symfony/Component/DomCrawler/Crawler.php:604
    .../src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php:16

    2) Symfony\Bundle\SecurityBundle\Tests\Functional\LocalizedRoutesAsPathTest::testLoginLogoutProcedure with data set #1 ('de')
    InvalidArgumentException: The current node list is empty.

    .../src/Symfony/Component/DomCrawler/Crawler.php:604
    .../src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php:16

    --

    There were 4 failures:

    1) Symfony\Bundle\SecurityBundle\Tests\Functional\LocalizedRoutesAsPathTest::testAccessRestrictedResource with data set #0 ('en')
    Failed asserting that two strings are equal.
    --- Expected
    +++ Actual
    @@ @@
    -http://localhost/en/login
    +http://localhost/login

    .../src/Symfony/Bundle/Securitybundle/Tests/Functional/WebTestCase.php:22
    .../src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php:38

    2) Symfony\Bundle\SecurityBundle\Tests\Functional\LocalizedRoutesAsPathTest::testAccessRestrictedResource with data set #1 ('de')
    Failed asserting that two strings are equal.
    --- Expected
    +++ Actual
    @@ @@
    -http://localhost/de/login
    +http://localhost/login

    .../src/Symfony/Bundle/Securitybundle/Tests/Functional/WebTestCase.php:22
    .../src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php:38

    3) Symfony\Bundle\SecurityBundle\Tests\Functional\LocalizedRoutesAsPathTest::testAccessRestrictedResourceWithForward with data set #0 ('en')
    HTTP/1.0 302 Found
    Cache-Control:  no-cache
    Content-Length: 299
    Content-Type:   text/html; charset=UTF-8
    Date:           Wed, 20 Jul 2011 05:36:27 GMT
    Location:       http://localhost/login
    Set-Cookie: PHPSESSID=11c9c6a7e7620e13bddef223a5ba46d9; path=/; domain=

    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <meta http-equiv="refresh" content="1;url=http://localhost/login" />
        </head>
        <body>
            Redirecting to <a href="http://localhost/login">http://localhost/login</a>.
        </body>
    </html>
    Failed asserting that <integer:0> matches expected <integer:1>.

    .../src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php:50

    4) Symfony\Bundle\SecurityBundle\Tests\Functional\LocalizedRoutesAsPathTest::testAccessRestrictedResourceWithForward with data set #1 ('de')
    HTTP/1.0 302 Found
    Cache-Control:  no-cache
    Content-Length: 299
    Content-Type:   text/html; charset=UTF-8
    Date:           Wed, 20 Jul 2011 05:36:28 GMT
    Location:       http://localhost/login
    Set-Cookie: PHPSESSID=2bbe63786a088471ade3717917f4ba4f; path=/; domain=

    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <meta http-equiv="refresh" content="1;url=http://localhost/login" />
        </head>
        <body>
            Redirecting to <a href="http://localhost/login">http://localhost/login</a>.
        </body>
    </html>
    Failed asserting that <integer:0> matches expected <integer:1>.

    .../src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php:50

---------------------------------------------------------------------------

by schmittjoh at 2011/07/19 23:47:29 -0700

I fixed a wrong case, but I couldn't reproduce the other errors (tested on Ubuntu).

My guess is that the temporary directory on your machine couldn't be deleted for some reason, and the test runs with the configuration of some of the previous tests.

---------------------------------------------------------------------------

by fabpot at 2011/07/20 00:28:41 -0700

That does not make any difference for me. For instance, in `LocalizedRoutesAsPathTest::testLoginLogoutProcedure()`, the first request to `'/'.$locale.'/login'` returns the following Response:

    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <meta http-equiv="refresh" content="1;url=http://localhost/login" />
        </head>
        <body>
            Redirecting to <a href="http://localhost/login">http://localhost/login</a>.
        </body>
    </html>

---------------------------------------------------------------------------

by schmittjoh at 2011/07/20 00:31:34 -0700

That's weird, did you make sure that the temporary directory does not exist?

``rm -Rf /tmp/StandardFormLogin/``

On Wed, Jul 20, 2011 at 9:28 AM, fabpot <
reply@reply.github.com>wrote:

> That does not make any difference for me. For instance, in
> `LocalizedRoutesAsPathTest::testLoginLogoutProcedure()`, the first request
> to `'/'.$locale.'/login'` returns the following Response:
>
>    <html>
>        <head>
>            <meta http-equiv="Content-Type" content="text/html;
> charset=utf-8" />
>            <meta http-equiv="refresh" content="1;url=
> http://localhost/login" />
>        </head>
>        <body>
>            Redirecting to <a href="http://localhost/login">
> http://localhost/login</a>.
>        </body>
>    </html>
>
> --
> Reply to this email directly or view it on GitHub:
> https://github.com/symfony/symfony/pull/1739#issuecomment-1613504
>

---------------------------------------------------------------------------

by fabpot at 2011/07/20 00:33:40 -0700

Yes, I've just checked and the directory does not exist.

---------------------------------------------------------------------------

by schmittjoh at 2011/07/20 00:39:55 -0700

Sorry, I can't reproduce it on Ubuntu and unless someone wants to sponsor me a Mac, there is not much I can do.
This commit is contained in:
Fabien Potencier 2011-07-22 14:45:54 +02:00
commit aab0bf7e2c
23 changed files with 403 additions and 46 deletions

View File

@ -84,6 +84,9 @@ RC4 to RC5
Session::getAttributes() -> Session::all()
Session::setAttributes() -> Session::replace()
* {_locale} is not supported in paths in the access_control section anymore. You can
rewrite the paths using a regular expression such as "(?:[a-z]{2})".
RC3 to RC4
----------

View File

@ -0,0 +1,15 @@
<?php
namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
class AuthenticationCommencingTest extends WebTestCase
{
public function testAuthenticationIsCommencingIfAccessDeniedExceptionIsWrapped()
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'config.yml'));
$client->insulate();
$client->request('GET', '/secure-but-not-covered-by-access-control');
$this->assertRedirect($client->getResponse(), '/login');
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\FormLoginBundle\Controller;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\DependencyInjection\ContainerAware;
class LocalizedController extends ContainerAware
{
public function loginAction()
{
// get the login error if there is one
if ($this->container->get('request')->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $this->container->get('request')->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $this->container->get('request')->getSession()->get(SecurityContext::AUTHENTICATION_ERROR);
}
return $this->container->get('templating')->renderResponse('FormLoginBundle:Localized:login.html.twig', array(
// last username entered by the user
'last_username' => $this->container->get('request')->getSession()->get(SecurityContext::LAST_USERNAME),
'error' => $error,
));
}
public function loginCheckAction()
{
throw new \RuntimeException('loginCheckAction() should never be called.');
}
public function logoutAction()
{
throw new \RuntimeException('logoutAction() should never be called.');
}
public function secureAction()
{
throw new \RuntimeException('secureAction() should never be called.');
}
public function profileAction()
{
return new Response('Profile');
}
public function homepageAction()
{
return new Response('Homepage');
}
}

View File

@ -11,6 +11,7 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\FormLoginBundle\Controller;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\DependencyInjection\ContainerAware;
@ -42,4 +43,9 @@ class LoginController extends ContainerAware
{
return new Response('', 400);
}
public function secureAction()
{
throw new \Exception('Wrapper', 0, new \Exception('Another Wrapper', 0, new AccessDeniedException()));
}
}

View File

@ -0,0 +1,30 @@
localized_login_path:
pattern: /{_locale}/login
defaults: { _controller: FormLoginBundle:Localized:login }
requirements: { _locale: "^[a-z]{2}$" }
localized_check_path:
pattern: /{_locale}/login_check
defaults: { _controller: FormLoginBundle:Localized:loginCheck }
requirements: { _locale: "^[a-z]{2}$" }
localized_default_target_path:
pattern: /{_locale}/profile
defaults: { _controller: FormLoginBundle:Localized:profile }
requirements: { _locale: "^[a-z]{2}$" }
localized_logout_path:
pattern: /{_locale}/logout
defaults: { _controller: FormLoginBundle:Localized:logout }
requirements: { _locale: "^[a-z]{2}$" }
localized_logout_target_path:
pattern: /{_locale}/
defaults: { _controller: FormLoginBundle:Localized:homepage }
requirements: { _locale: "^[a-z]{2}$" }
localized_secure_path:
pattern: /{_locale}/secure/
defaults: { _controller: FormLoginBundle:Localized:secure }
requirements: { _locale: "^[a-z]{2}$" }

View File

@ -14,6 +14,17 @@ form_login_custom_target_path:
pattern: /foo
defaults: { _controller: FormLoginBundle:Login:afterLogin }
form_login_default_target_path:
pattern: /profile
defaults: { _controller: FormLoginBundle:Login:afterLogin }
form_login_redirect_to_protected_resource_after_login:
pattern: /protected-resource
defaults: { _controller: FormLoginBundle:Login:afterLogin }
form_logout:
pattern: /logout_path
form_secure_action:
pattern: /secure-but-not-covered-by-access-control
defaults: { _controller: FormLoginBundle:Login:secure }

View File

@ -0,0 +1,21 @@
{% extends "::base.html.twig" %}
{% block body %}
{% if error %}
<div>{{ error.message }}</div>
{% endif %}
<form action="{{ path('localized_check_path') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" />
<label for="password">Password:</label>
<input type="password" id="password" name="_password" />
<input type="hidden" name="_target_path" value="" />
<input type="submit" name="login" />
</form>
{% endblock %}

View File

@ -16,25 +16,33 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
*/
class FormLoginTest extends WebTestCase
{
public function testFormLogin()
/**
* @dataProvider getConfigs
*/
public function testFormLogin($config)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin'));
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
$client->insulate();
$form = $client->request('GET', '/login')->selectButton('login')->form();
$form['_username'] = 'johannes';
$form['_password'] = 'test';
$client->submit($form);
$this->assertRedirect($client->getResponse(), '/');
$this->assertRedirect($client->getResponse(), '/profile');
$text = $client->followRedirect()->text();
$this->assertContains('Hello johannes!', $text);
$this->assertContains('You\'re browsing to path "/".', $text);
$this->assertContains('You\'re browsing to path "/profile".', $text);
}
public function testFormLoginWithCustomTargetPath()
/**
* @dataProvider getConfigs
*/
public function testFormLoginWithCustomTargetPath($config)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin'));
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
$client->insulate();
$form = $client->request('GET', '/login')->selectButton('login')->form();
$form['_username'] = 'johannes';
@ -49,9 +57,13 @@ class FormLoginTest extends WebTestCase
$this->assertContains('You\'re browsing to path "/foo".', $text);
}
public function testFormLoginRedirectsToProtectedResourceAfterLogin()
/**
* @dataProvider getConfigs
*/
public function testFormLoginRedirectsToProtectedResourceAfterLogin($config)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin'));
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
$client->insulate();
$client->request('GET', '/protected-resource');
$this->assertRedirect($client->getResponse(), '/login');
@ -67,6 +79,14 @@ class FormLoginTest extends WebTestCase
$this->assertContains('You\'re browsing to path "/protected-resource".', $text);
}
public function getConfigs()
{
return array(
array('config.yml'),
array('routes_as_path.yml'),
);
}
protected function setUp()
{
parent::setUp();

View File

@ -0,0 +1,71 @@
<?php
namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
class LocalizedRoutesAsPathTest extends WebTestCase
{
/**
* @dataProvider getLocales
*/
public function testLoginLogoutProcedure($locale)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes.yml'));
$client->insulate();
$crawler = $client->request('GET', '/'.$locale.'/login');
$form = $crawler->selectButton('login')->form();
$form['_username'] = 'johannes';
$form['_password'] = 'test';
$client->submit($form);
$this->assertRedirect($client->getResponse(), '/'.$locale.'/profile');
$this->assertEquals('Profile', $client->followRedirect()->text());
$client->request('GET', '/'.$locale.'/logout');
$this->assertRedirect($client->getResponse(), '/'.$locale.'/');
$this->assertEquals('Homepage', $client->followRedirect()->text());
}
/**
* @dataProvider getLocales
*/
public function testAccessRestrictedResource($locale)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes.yml'));
$client->insulate();
$client->request('GET', '/'.$locale.'/secure/');
$this->assertRedirect($client->getResponse(), '/'.$locale.'/login');
}
/**
* @dataProvider getLocales
*/
public function testAccessRestrictedResourceWithForward($locale)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes_with_forward.yml'));
$client->insulate();
$crawler = $client->request('GET', '/'.$locale.'/secure/');
$this->assertEquals(1, count($crawler->selectButton('login')), (string) $client->getResponse());
}
public function getLocales()
{
return array(array('en'), array('de'));
}
protected function setUp()
{
parent::setUp();
$this->deleteTmpDir('StandardFormLogin');
}
protected function tearDown()
{
parent::setUp();
$this->deleteTmpDir('StandardFormLogin');
}
}

View File

@ -13,25 +13,37 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
class SecurityRoutingIntegrationTest extends WebTestCase
{
public function testRoutingErrorIsNotExposedForProtectedResourceWhenAnonymous()
/**
* @dataProvider getConfigs
*/
public function testRoutingErrorIsNotExposedForProtectedResourceWhenAnonymous($config)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin'));
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
$client->insulate();
$client->request('GET', '/protected_resource');
$this->assertRedirect($client->getResponse(), '/login');
}
public function testRoutingErrorIsExposedWhenNotProtected()
/**
* @dataProvider getConfigs
*/
public function testRoutingErrorIsExposedWhenNotProtected($config)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin'));
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
$client->insulate();
$client->request('GET', '/unprotected_resource');
$this->assertEquals(404, $client->getResponse()->getStatusCode());
$this->assertEquals(404, $client->getResponse()->getStatusCode(), (string) $client->getResponse());
}
public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWithInsufficientRights()
/**
* @dataProvider getConfigs
*/
public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWithInsufficientRights($config)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin'));
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
$client->insulate();
$form = $client->request('GET', '/login')->selectButton('login')->form();
$form['_username'] = 'johannes';
@ -43,6 +55,11 @@ class SecurityRoutingIntegrationTest extends WebTestCase
$this->assertNotEquals(404, $client->getResponse()->getStatusCode());
}
public function getConfigs()
{
return array(array('config.yml'), array('routes_as_path.yml'));
}
protected function setUp()
{
parent::setUp();

View File

@ -18,7 +18,7 @@ class WebTestCase extends BaseWebTestCase
{
static public function assertRedirect($response, $location)
{
self::assertTrue($response->isRedirect());
self::assertTrue($response->isRedirect(), 'Response is not a redirect, got status code: '.$response->getStatusCode());
self::assertEquals('http://localhost'.$location, $response->headers->get('Location'));
}

View File

@ -11,8 +11,21 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
use Symfony\Component\HttpKernel\Util\Filesystem;
// get the autoload file
$dir = __DIR__;
$lastDir = null;
while ($dir !== $lastDir) {
$lastDir = $dir;
if (file_exists($dir.'/autoload.php.dist')) {
require_once $dir.'/autoload.php.dist';
break;
}
$dir = dirname($dir);
}
use Symfony\Component\HttpKernel\Util\Filesystem;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\HttpKernel\Kernel;
@ -33,10 +46,11 @@ class AppKernel extends Kernel
}
$this->testCase = $testCase;
if (!file_exists($filename = __DIR__.'/'.$testCase.'/'.$rootConfig)) {
throw new \InvalidArgumentException(sprintf('The root config "%s" does not exist.', $filename));
$fs = new Filesystem();
if (!$fs->isAbsolutePath($rootConfig) && !file_exists($rootConfig = __DIR__.'/'.$testCase.'/'.$rootConfig)) {
throw new \InvalidArgumentException(sprintf('The root config "%s" does not exist.', $rootConfig));
}
$this->rootConfig = $filename;
$this->rootConfig = $rootConfig;
parent::__construct($environment, $debug);
}
@ -74,6 +88,16 @@ class AppKernel extends Kernel
$loader->load($this->rootConfig);
}
public function serialize()
{
return serialize(array($this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug()));
}
public function unserialize($str)
{
call_user_func_array(array($this, '__construct'), unserialize($str));
}
protected function getKernelParameters()
{
$parameters = parent::getKernelParameters();

View File

@ -21,9 +21,11 @@ security:
default:
form_login:
check_path: /login_check
default_target_path: /profile
anonymous: ~
access_control:
- { path: ^/unprotected_resource$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/secure-but-not-covered-by-access-control$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/highly_protected_resource$, roles: IS_ADMIN }
- { path: .*, roles: IS_AUTHENTICATED_FULLY }

View File

@ -0,0 +1,26 @@
imports:
- { resource: ./../config/default.yml }
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
providers:
in_memory:
users:
johannes: { password: test, roles: [ROLE_USER] }
firewalls:
default:
form_login:
login_path: localized_login_path
check_path: localized_check_path
default_target_path: localized_default_target_path
logout:
path: localized_logout_path
target: localized_logout_target_path
anonymous: ~
access_control:
- { path: '^/(?:[a-z]{2})/secure/.*', roles: ROLE_USER }

View File

@ -0,0 +1,9 @@
imports:
- { resource: ./localized_routes.yml }
security:
firewalls:
default:
form_login:
use_forward: true
failure_forward: true

View File

@ -0,0 +1,13 @@
imports:
- { resource: ./config.yml }
security:
firewalls:
default:
form_login:
login_path: form_login
check_path: form_login_check
default_target_path: form_login_default_target_path
logout:
path: form_logout
target: form_login_homepage

View File

@ -1,2 +1,5 @@
_form_login_bundle:
resource: @FormLoginBundle/Resources/config/routing.yml
_form_login_localized:
resource: @FormLoginBundle/Resources/config/localized_routing.yml

View File

@ -9,9 +9,8 @@ framework:
test: ~
session:
default_locale: en
lifetime: 3600
auto_start: true
storage_id: session.storage.filesystem
storage_id: session.storage.filesystem
services:
logger: { class: Symfony\Component\HttpKernel\Log\NullLogger }

View File

@ -104,11 +104,7 @@ class RequestMatcher implements RequestMatcherInterface
}
if (null !== $this->path) {
if (null !== $session = $request->getSession()) {
$path = strtr($this->path, array('{_locale}' => $session->getLocale(), '#' => '\\#'));
} else {
$path = str_replace('#', '\\#', $this->path);
}
$path = str_replace('#', '\\#', $this->path);
if (!preg_match('#'.$path.'#', $request->getPathInfo())) {
return false;

View File

@ -76,6 +76,11 @@ class ExceptionListener
$exception = $event->getException();
$request = $event->getRequest();
// determine the actual cause for the exception
while (null !== $previous = $exception->getPrevious()) {
$exception = $previous;
}
if ($exception instanceof AuthenticationException) {
if (null !== $this->logger) {
$this->logger->info(sprintf('Authentication exception occurred; redirecting to authentication entry point (%s)', $exception->getMessage()));

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Security\Http;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
@ -45,22 +47,10 @@ class HttpUtils
*/
public function createRedirectResponse(Request $request, $path, $status = 302)
{
if (0 === strpos($path, '/')) {
if ('/' === $path[0]) {
$path = $request->getUriForPath($path);
} elseif (0 !== strpos($path, 'http')) {
// hack (don't have a better solution for now)
$context = $this->router->getContext();
try {
$parameters = $this->router->match($request->getPathInfo());
} catch (\Exception $e) {
}
if (isset($parameters['_locale'])) {
$context->setParameter('_locale', $parameters['_locale']);
} elseif ($session = $request->getSession()) {
$context->setParameter('_locale', $session->getLocale());
}
$this->resetLocale($request);
$path = $this->generateUrl($path, true);
}
@ -78,10 +68,26 @@ class HttpUtils
public function createRequest(Request $request, $path)
{
if ($path && '/' !== $path[0] && 0 !== strpos($path, 'http')) {
$this->resetLocale($request);
$path = $this->generateUrl($path, true);
}
return Request::create($path, 'get', array(), $request->cookies->all(), array(), $request->server->all());
$newRequest = Request::create($path, 'get', array(), $request->cookies->all(), array(), $request->server->all());
if ($session = $request->getSession()) {
$newRequest->setSession($session);
}
if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
$newRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR));
}
if ($request->attributes->has(SecurityContextInterface::ACCESS_DENIED_ERROR)) {
$newRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $request->attributes->get(SecurityContextInterface::ACCESS_DENIED_ERROR));
}
if ($request->attributes->has(SecurityContextInterface::LAST_USERNAME)) {
$newRequest->attributes->set(SecurityContextInterface::LAST_USERNAME, $request->attributes->get(SecurityContextInterface::LAST_USERNAME));
}
return $newRequest;
}
/**
@ -107,6 +113,27 @@ class HttpUtils
return $path === $request->getPathInfo();
}
// hack (don't have a better solution for now)
private function resetLocale(Request $request)
{
$context = $this->router->getContext();
if ($context->getParameter('_locale')) {
return;
}
try {
$parameters = $this->router->match($request->getPathInfo());
if (isset($parameters['_locale'])) {
$context->setParameter('_locale', $parameters['_locale']);
} elseif ($session = $request->getSession()) {
$context->setParameter('_locale', $session->getLocale());
}
} catch (\Exception $e) {
// let's hope user doesn't use the locale in the path
}
}
private function generateUrl($route, $absolute = false)
{
if (null === $this->router) {

View File

@ -142,7 +142,7 @@ class RequestMatcherTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($matcher->matches($request));
}
public function testPathWithLocale()
public function testPathWithLocaleIsNotSupported()
{
$matcher = new RequestMatcher();
$request = Request::create('/en/login');
@ -152,9 +152,6 @@ class RequestMatcherTest extends \PHPUnit_Framework_TestCase
$request->setSession($session);
$matcher->matchPath('^/{_locale}/login$');
$this->assertTrue($matcher->matches($request));
$session->setLocale('de');
$this->assertFalse($matcher->matches($request));
}

View File

@ -61,6 +61,17 @@ class HttpUtilsTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('bar', $subRequest->server->get('Foo'));
// route name
$utils = new HttpUtils($router = $this->getMockBuilder('Symfony\Component\Routing\Router')->disableOriginalConstructor()->getMock());
$router
->expects($this->once())
->method('generate')
->will($this->returnValue('/foo/bar'))
;
$router
->expects($this->any())
->method('getContext')
->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext')))
;
$subRequest = $utils->createRequest($this->getRequest(), 'foobar');
$this->assertEquals('/foo/bar', $subRequest->getPathInfo());