merged branch flojon/patch-3 (PR #5984)
This PR was merged into the 2.0 branch. Commits -------64b54dc
Use better default ports in urlRedirectAction64216f2
Add tests for urlRedirectAction Discussion ---------- Default to current port in urlRedirectAction I was a bit surprised when I used urlRedirectAction from a non-standard port (8000) it redirected me to port 80. I would argue that the default should be to use the current port instead. This is a simple patch to change that. This should only break in the case someone is relying on the current default to redirect from a non-standard port to the standard port, which should be a really rare case... --------------------------------------------------------------------------- by Tobion at 2012-11-11T20:29:54Z The idea is right but the implementation not. Seems this patch is not as "simple" as you said. When you're on HTTPS and want to redirect to $scheme = HTTP, then it still uses the current HTTPS port which is wrong. --------------------------------------------------------------------------- by flojon at 2012-11-11T20:36:47Z Ah, I see the problem. So I guess the correct behavior would be to use the current port if staying with the same scheme or go to standard port if switching scheme. Unless the user has specified a port which will always override... --------------------------------------------------------------------------- by Tobion at 2012-11-11T20:42:18Z That would be the best solution that is currently possible but not the best solution that should be possible. Because if you switch scheme but the other scheme does not use the standard port, it still doesn't work. Ideally the Request class had an option that allows to define the ports symfony should use for HTTP and HTTPS. This logic is in RequestContext, but it's not used here. --------------------------------------------------------------------------- by flojon at 2012-11-11T21:32:55Z Bummer, I forgot to check if the current port is a standard port... --------------------------------------------------------------------------- by Tobion at 2012-11-11T21:35:13Z add some tests --------------------------------------------------------------------------- by flojon at 2012-11-11T23:28:18Z Added tests and fixed my previous error --------------------------------------------------------------------------- by flojon at 2012-11-15T18:25:12Z @Tobion is there anything else I needed for this? --------------------------------------------------------------------------- by fabpot at 2012-11-19T12:56:04Z To be consistent with how we manage HTTP ports elsewhere, I'd rather use the values of the `request_listener.http_port` and `request_listener.https_port`: ```php if (null === $httpPort) { $httpPort = $this->container->getParameter('request_listener.http_port'); } if (null === $httpsPort) { $httpsPort = $this->container->getParameter('request_listener.https_port'); } ``` This is done in the `security.authentication.retry_entry_point` service and for the `router_listener` listener. The parameter name is probably not the best one, but that could be changed then in master. --------------------------------------------------------------------------- by flojon at 2012-11-19T13:49:18Z @fabpot But then you would need to set that parameter manually right? It wouldn't automatically redirect you to the same port, which was what I wanted to achieve... Could this be the right order of preference: If a value was specified in the route use that. Otherwise use the current port unless switching scheme then use the parameter value --------------------------------------------------------------------------- by fabpot at 2012-11-19T13:52:17Z Your order of preference looks good to me. --------------------------------------------------------------------------- by flojon at 2012-11-19T19:13:19Z Man this was more involved than I thought... :) Changed the logic to use the parameters when not using the current port. Also tried clean up the tests a little bit... Enjoy!
This commit is contained in:
commit
ebd5e9286c
@ -64,7 +64,7 @@ class RedirectController extends ContainerAware
|
|||||||
*
|
*
|
||||||
* @return Response A Response instance
|
* @return Response A Response instance
|
||||||
*/
|
*/
|
||||||
public function urlRedirectAction($path, $permanent = false, $scheme = null, $httpPort = 80, $httpsPort = 443)
|
public function urlRedirectAction($path, $permanent = false, $scheme = null, $httpPort = null, $httpsPort = null)
|
||||||
{
|
{
|
||||||
if (!$path) {
|
if (!$path) {
|
||||||
return new Response(null, 410);
|
return new Response(null, 410);
|
||||||
@ -88,10 +88,28 @@ class RedirectController extends ContainerAware
|
|||||||
}
|
}
|
||||||
|
|
||||||
$port = '';
|
$port = '';
|
||||||
if ('http' === $scheme && 80 != $httpPort) {
|
if ('http' === $scheme) {
|
||||||
$port = ':'.$httpPort;
|
if ($httpPort == null) {
|
||||||
} elseif ('https' === $scheme && 443 != $httpsPort) {
|
if ('http' === $request->getScheme()) {
|
||||||
$port = ':'.$httpsPort;
|
$httpPort = $request->getPort();
|
||||||
|
} else {
|
||||||
|
$httpPort = $this->container->getParameter('request_listener.http_port');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($httpPort != null && $httpPort != 80) {
|
||||||
|
$port = ":$httpPort";
|
||||||
|
}
|
||||||
|
} else if ('https' === $scheme) {
|
||||||
|
if ($httpsPort == null) {
|
||||||
|
if ('https' === $request->getScheme()) {
|
||||||
|
$httpsPort = $request->getPort();
|
||||||
|
} else {
|
||||||
|
$httpsPort = $this->container->getParameter('request_listener.https_port');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($httpsPort != null && $httpsPort != 443) {
|
||||||
|
$port = ":$httpsPort";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$path.$qs;
|
$url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$path.$qs;
|
||||||
|
@ -109,4 +109,131 @@ class RedirectControllerTest extends TestCase
|
|||||||
$this->assertEquals('http://foo.bar/', $returnResponse->headers->get('Location'));
|
$this->assertEquals('http://foo.bar/', $returnResponse->headers->get('Location'));
|
||||||
$this->assertEquals(302, $returnResponse->getStatusCode());
|
$this->assertEquals(302, $returnResponse->getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testUrlRedirectDefaultPortParameters()
|
||||||
|
{
|
||||||
|
$host = 'www.example.com';
|
||||||
|
$baseUrl = '/base';
|
||||||
|
$path = '/redirect-path';
|
||||||
|
$httpPort = 1080;
|
||||||
|
$httpsPort = 1443;
|
||||||
|
|
||||||
|
$expectedUrl = "https://$host:$httpsPort$baseUrl$path";
|
||||||
|
$request = $this->createRequestObject('http', $host, $httpPort, $baseUrl);
|
||||||
|
$controller = $this->createRedirectController($request, null, $httpsPort);
|
||||||
|
$returnValue = $controller->urlRedirectAction($path, false, 'https');
|
||||||
|
$this->assertRedirectUrl($returnValue, $expectedUrl);
|
||||||
|
|
||||||
|
$expectedUrl = "http://$host:$httpPort$baseUrl$path";
|
||||||
|
$request = $this->createRequestObject('https', $host, $httpPort, $baseUrl);
|
||||||
|
$controller = $this->createRedirectController($request, $httpPort);
|
||||||
|
$returnValue = $controller->urlRedirectAction($path, false, 'http');
|
||||||
|
$this->assertRedirectUrl($returnValue, $expectedUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function urlRedirectProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// Standard ports
|
||||||
|
array('http', null, null, 'http', 80, ""),
|
||||||
|
array('http', 80, null, 'http', 80, ""),
|
||||||
|
array('https', null, null, 'http', 80, ""),
|
||||||
|
array('https', 80, null, 'http', 80, ""),
|
||||||
|
|
||||||
|
array('http', null, null, 'https', 443, ""),
|
||||||
|
array('http', null, 443, 'https', 443, ""),
|
||||||
|
array('https', null, null, 'https', 443, ""),
|
||||||
|
array('https', null, 443, 'https', 443, ""),
|
||||||
|
|
||||||
|
// Non-standard ports
|
||||||
|
array('http', null, null, 'http', 8080, ":8080"),
|
||||||
|
array('http', 4080, null, 'http', 8080, ":4080"),
|
||||||
|
array('http', 80, null, 'http', 8080, ""),
|
||||||
|
array('https', null, null, 'http', 8080, ""),
|
||||||
|
array('https', null, 8443, 'http', 8080, ":8443"),
|
||||||
|
array('https', null, 443, 'http', 8080, ""),
|
||||||
|
|
||||||
|
array('https', null, null, 'https', 8443, ":8443"),
|
||||||
|
array('https', null, 4443, 'https', 8443, ":4443"),
|
||||||
|
array('https', null, 443, 'https', 8443, ""),
|
||||||
|
array('http', null, null, 'https', 8443, ""),
|
||||||
|
array('http', 8080, 4443, 'https', 8443, ":8080"),
|
||||||
|
array('http', 80, 4443, 'https', 8443, ""),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider urlRedirectProvider
|
||||||
|
*/
|
||||||
|
public function testUrlRedirect($scheme, $httpPort, $httpsPort, $requestScheme, $requestPort, $expectedPort)
|
||||||
|
{
|
||||||
|
$host = 'www.example.com';
|
||||||
|
$baseUrl = '/base';
|
||||||
|
$path = '/redirect-path';
|
||||||
|
$expectedUrl = "$scheme://$host$expectedPort$baseUrl$path";
|
||||||
|
|
||||||
|
$request = $this->createRequestObject($requestScheme, $host, $requestPort, $baseUrl);
|
||||||
|
$controller = $this->createRedirectController($request);
|
||||||
|
|
||||||
|
$returnValue = $controller->urlRedirectAction($path, false, $scheme, $httpPort, $httpsPort);
|
||||||
|
$this->assertRedirectUrl($returnValue, $expectedUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createRequestObject($scheme, $host, $port, $baseUrl)
|
||||||
|
{
|
||||||
|
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
|
||||||
|
$request
|
||||||
|
->expects($this->any())
|
||||||
|
->method('getScheme')
|
||||||
|
->will($this->returnValue($scheme));
|
||||||
|
$request
|
||||||
|
->expects($this->any())
|
||||||
|
->method('getHost')
|
||||||
|
->will($this->returnValue($host));
|
||||||
|
$request
|
||||||
|
->expects($this->any())
|
||||||
|
->method('getPort')
|
||||||
|
->will($this->returnValue($port));
|
||||||
|
$request
|
||||||
|
->expects($this->any())
|
||||||
|
->method('getBaseUrl')
|
||||||
|
->will($this->returnValue($baseUrl));
|
||||||
|
|
||||||
|
return $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createRedirectController($request, $httpPort = null, $httpsPort = null)
|
||||||
|
{
|
||||||
|
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
|
||||||
|
$container
|
||||||
|
->expects($this->at(0))
|
||||||
|
->method('get')
|
||||||
|
->with($this->equalTo('request'))
|
||||||
|
->will($this->returnValue($request));
|
||||||
|
if ($httpPort != null) {
|
||||||
|
$container
|
||||||
|
->expects($this->at(1))
|
||||||
|
->method('getParameter')
|
||||||
|
->with($this->equalTo('request_listener.http_port'))
|
||||||
|
->will($this->returnValue($httpPort));
|
||||||
|
}
|
||||||
|
if ($httpsPort != null) {
|
||||||
|
$container
|
||||||
|
->expects($this->at(1))
|
||||||
|
->method('getParameter')
|
||||||
|
->with($this->equalTo('request_listener.https_port'))
|
||||||
|
->will($this->returnValue($httpsPort));
|
||||||
|
}
|
||||||
|
|
||||||
|
$controller = new RedirectController();
|
||||||
|
$controller->setContainer($container);
|
||||||
|
|
||||||
|
return $controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assertRedirectUrl($returnValue, $expectedUrl)
|
||||||
|
{
|
||||||
|
$this->assertTrue($returnValue->isRedirect($expectedUrl),
|
||||||
|
"Expected: $expectedUrl\nGot: " . $returnValue->headers->get('Location'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user