Commit a2259f1d authored by Igor Wiedler's avatar Igor Wiedler

Introduce real HTTPS support, RequestContextFactory

* Refactor RequestContext creation into a RequestContextFactory
* Fix RequestContext argument order (issue #63)
* Allow specifying default ports for HTTP and HTTPS
* Add Controller::requireSecure() to enforce HTTPS on routes
* Refactor UrlGeneratorExtensionTest
parent 8341f739
......@@ -196,6 +196,9 @@ of them.
$id = $app['request']->get('id');
This is only available when a request is being served, you can only access it
from within a controller, before filter, after filter or error handler.
* **autoloader**: This service provides you with a
`UniversalClassLoader
<http://api.symfony.com/2.0/Symfony/Component/ClassLoader/UniversalClassLoader.html>`_
......@@ -231,6 +234,31 @@ of them.
Symfony2, it takes a Request as input and returns a
Response as output.
* **request_context**: The request context is a simplified representation
of the request that is used by the Router and the UrlGenerator.
* **request_context.factory**: Is used internally to create a RequestContext
from a Request.
.. note::
All of these Silex core services are shared.
Core parameters
---------------
* **request.http_port** (optional): Allows you to override the default port
for non-HTTPS URLs. If the current request is HTTP, it will always use the
current port.
Defaults to 80.
This parameter can be used by the ``UrlGeneratorExtension``.
* **request.https_port** (optional): Allows you to override the default port
for HTTPS URLs. If the current request is HTTPS, it will always use the
current port.
Defaults to 443.
This parameter can be used by the ``UrlGeneratorExtension``.
......@@ -27,7 +27,6 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Matcher\Exception\Exception as MatcherException;
use Symfony\Component\Routing\Matcher\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Matcher\Exception\NotFoundException;
......@@ -80,6 +79,13 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
$this['kernel'] = $this->share(function () use ($app) {
return new HttpKernel($app['dispatcher'], $app['resolver']);
});
$this['request_context.factory'] = $this->share(function () {
return new RequestContextFactory();
});
$this['request.http_port'] = 80;
$this['request.https_port'] = 443;
}
/**
......@@ -312,13 +318,8 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
public function onCoreRequest(KernelEvent $event)
{
$this['request'] = $event->getRequest();
$this['request_context'] = new RequestContext(
$this['request']->getBaseUrl(),
$this['request']->getMethod(),
$this['request']->getHost(),
$this['request']->getPort(),
$this['request']->getScheme()
);
$this['request_context'] = $this['request_context.factory']->create($this['request'], $this['request.http_port'], $this['request.https_port']);
$this['controllers']->flush();
......
......@@ -95,6 +95,16 @@ class Controller
return $this;
}
/**
* Sets the requirement of HTTPS on this controller.
*/
public function requireSecure()
{
$this->route->setRequirement('_scheme', 'https');
return $this;
}
/**
* Freezes the controller.
*
......
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Silex;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RequestContext;
/**
* Creates a RequestContext from a Request.
*
* @author Igor Wiedler <igor@wiedler.ch>
*/
class RequestContextFactory
{
/**
* Creates the RequestContext instance.
*
* @param Request $request The input Request
* @param int $defaultHttpPort The default port for HTTP
* @param int $defaultHttpsPort The default port for HTTPS
*
* @return RequestContext the RequestContext
*/
public function create(Request $request, $defaultHttpPort = 80, $defaultHttpsPort = 443)
{
return new RequestContext(
$request->getBaseUrl(),
$request->getMethod(),
$request->getHost(),
$request->getScheme(),
!$request->isSecure() ? $request->getPort() : $defaultHttpPort,
$request->isSecure() ? $request->getPort() : $defaultHttpsPort
);
}
}
......@@ -32,12 +32,58 @@ class UrlGeneratorExtensionTest extends \PHPUnit_Framework_TestCase
$app->get('/hello/{name}', function ($name) {})
->bind('hello');
$app->get('/', function () use ($app) {
return $app['url_generator']->generate('hello', array('name' => 'john'));
});
$app['request'] = Request::create('/');
$app['request_context'] = $app['request_context.factory']->create($app['request']);
$request = Request::create('/');
$response = $app->handle($request);
$this->assertEquals('/hello/john', $response->getContent());
$this->assertInstanceOf('Symfony\Component\Routing\Generator\UrlGenerator', $app['url_generator']);
}
public function testUrlGeneration()
{
$app = new Application();
$app->register(new UrlGeneratorExtension());
$app->get('/hello/{name}', function ($name) {})
->bind('hello');
$app['request'] = Request::create('/');
$app['request_context'] = $app['request_context.factory']->create($app['request']);
$url = $app['url_generator']->generate('hello', array('name' => 'john'));
$this->assertEquals('/hello/john', $url);
}
public function testAbsoluteUrlGeneration()
{
$app = new Application();
$app->register(new UrlGeneratorExtension());
$app->get('/hello/{name}', function ($name) {})
->bind('hello');
$app['request'] = Request::create('https://localhost:81/');
$app['request_context'] = $app['request_context.factory']->create($app['request']);
$url = $app['url_generator']->generate('hello', array('name' => 'john'), true);
$this->assertEquals('https://localhost:81/hello/john', $url);
}
public function testUrlGenerationWithHttps()
{
$app = new Application();
$app->register(new UrlGeneratorExtension());
$app->get('/hello/{name}', function ($name) {})
->bind('hello')
->requireSecure();
$app['request'] = Request::create('http://localhost/');
$app['request_context'] = $app['request_context.factory']->create($app['request']);
$url = $app['url_generator']->generate('hello', array('name' => 'john'));
$this->assertEquals('https://localhost/hello/john', $url);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment