Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
These classes tie the various parts of Cake\Http into something useful. The BaseApplication is used by developers to define their middleware and bootstrap their application. The Server is used to dispatch requests into the Application and emit the responses.
- Loading branch information
Showing
7 changed files
with
574 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
<?php | ||
/** | ||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org) | ||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) | ||
* | ||
* Licensed under The MIT License | ||
* For full copyright and license information, please see the LICENSE.txt | ||
* Redistributions of files must retain the above copyright notice. | ||
* | ||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) | ||
* @link http://cakephp.org CakePHP(tm) Project | ||
* @since 3.3.0 | ||
* @license http://www.opensource.org/licenses/mit-license.php MIT License | ||
*/ | ||
namespace Cake\Http; | ||
|
||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
|
||
/** | ||
* Base class for application classes. | ||
* | ||
* The application class is responsible for bootstrapping the application, | ||
* and ensuring that middleware is attached. It is also invoked as the last piece | ||
* of middleware, and delegates request/response handling to the correct controller. | ||
*/ | ||
abstract class BaseApplication | ||
{ | ||
|
||
/** | ||
* @var string Contains the path of the config directory | ||
*/ | ||
protected $configDir; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param string $configDir The directory the bootstrap configuration is held in. | ||
*/ | ||
public function __construct($configDir) | ||
{ | ||
$this->configDir = $configDir; | ||
} | ||
|
||
/** | ||
* @param \Cake\Http\MiddlewareStack $middleware The middleware stack to set in your App Class | ||
* @return \Cake\Http\MiddlewareStack | ||
*/ | ||
abstract public function middleware($middleware); | ||
|
||
/** | ||
* Load all the application configuration and bootstrap logic. | ||
* | ||
* @return void | ||
*/ | ||
public function bootstrap() | ||
{ | ||
// Load traditional bootstrap file.. | ||
require_once $this->configDir . '/bootstrap.php'; | ||
|
||
// Load other config files your application needs. | ||
} | ||
|
||
/** | ||
* Invoke the application. | ||
* | ||
* - Convert the PSR request/response into CakePHP equivalents. | ||
* - Create the controller that will handle this request. | ||
* - Invoke the controller. | ||
* | ||
* @param \Psr\Http\Message\ServerRequestInterface $request The request | ||
* @param \Psr\Http\Message\ResponseInterface $response The response | ||
* @param callable $next The next middleware | ||
* @return \Psr\Http\Message\ResponseInterface | ||
*/ | ||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next) | ||
{ | ||
// Convert the request/response to CakePHP equivalents. | ||
$cakeRequest = RequestTransformer::toCake($request); | ||
$cakeResponse = ResponseTransformer::toCake($response); | ||
|
||
// Dispatch the request/response to CakePHP | ||
$cakeResponse = $this->getDispatcher()->dispatch($cakeRequest, $cakeResponse); | ||
|
||
// Convert the response back into a PSR7 object. | ||
return $next($request, ResponseTransformer::toPsr($cakeResponse)); | ||
} | ||
|
||
/** | ||
* Get the ActionDispatcher. | ||
* | ||
* @return \Spekkoek\ActionDispatcher | ||
*/ | ||
protected function getDispatcher() | ||
{ | ||
return new ActionDispatcher(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
<?php | ||
/** | ||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org) | ||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) | ||
* | ||
* Licensed under The MIT License | ||
* For full copyright and license information, please see the LICENSE.txt | ||
* Redistributions of files must retain the above copyright notice. | ||
* | ||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) | ||
* @link http://cakephp.org CakePHP(tm) Project | ||
* @since 3.3.0 | ||
* @license http://www.opensource.org/licenses/mit-license.php MIT License | ||
*/ | ||
namespace Cake\Http; | ||
|
||
use Cake\Event\EventDispatcherTrait; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
use RuntimeException; | ||
use Zend\Diactoros\Response; | ||
use Zend\Diactoros\Response\EmitterInterface; | ||
use Zend\Diactoros\Response\SapiStreamEmitter; | ||
|
||
/** | ||
* Runs an application invoking all the PSR7 middleware and the registered application. | ||
*/ | ||
class Server | ||
{ | ||
|
||
use EventDispatcherTrait; | ||
|
||
/** | ||
* @var \Cake\Http\BaseApplication | ||
*/ | ||
protected $app; | ||
|
||
/** | ||
* @var \Cake\Http\Runner | ||
*/ | ||
protected $runner; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param \Cake\Http\BaseApplication $app The application to use. | ||
*/ | ||
public function __construct(BaseApplication $app) | ||
{ | ||
$this->setApp($app); | ||
$this->setRunner(new Runner()); | ||
} | ||
|
||
/** | ||
* Run the request/response through the Application and its middleware. | ||
* | ||
* This will invoke the following methods: | ||
* | ||
* - App->bootstrap() - Perform any bootstrapping logic for your application here. | ||
* - App->middleware() - Attach any application middleware here. | ||
* - Trigger the 'Server.buildMiddleware' event. You can use this to modify the | ||
* from event listeners. | ||
* - Run the middleware stack including the application. | ||
* | ||
* @param \Psr\Http\Message\ServerRequestInterface $request The request to use or null. | ||
* @param \Psr\Http\Message\ResponseInterface $response The response to use or null. | ||
* @return \Psr\Http\Message\ResponseInterface | ||
* @throws \RuntimeException When the application does not make a response. | ||
*/ | ||
public function run(ServerRequestInterface $request = null, ResponseInterface $response = null) | ||
{ | ||
$this->app->bootstrap(); | ||
$request = $request ?: ServerRequestFactory::fromGlobals(); | ||
$response = $response ?: new Response(); | ||
|
||
$middleware = $this->app->middleware(new MiddlewareStack()); | ||
if (!($middleware instanceof MiddlewareStack)) { | ||
throw new RuntimeException('The application `middleware` method did not return a middleware stack.'); | ||
} | ||
$middleware->push($this->app); | ||
$this->dispatchEvent('Server.buildMiddleware', ['middleware' => $middleware]); | ||
$response = $this->runner->run($middleware, $request, $response); | ||
|
||
if (!($response instanceof ResponseInterface)) { | ||
throw new RuntimeException(sprintf( | ||
'Application did not create a response. Got "%s" instead.', | ||
is_object($response) ? get_class($response) : $response | ||
)); | ||
} | ||
return $response; | ||
} | ||
|
||
/** | ||
* Emit the response using the PHP SAPI. | ||
* | ||
* @param \Psr\Http\Message\ResponseInterface $response The response to emit | ||
* @param \Zend\Diactoros\Response\EmitterInterface $emitter The emitter to use. | ||
* When null, a SAPI Stream Emitter will be used. | ||
* @return void | ||
*/ | ||
public function emit(ResponseInterface $response, EmitterInterface $emitter = null) | ||
{ | ||
if (!$emitter) { | ||
$emitter = new SapiStreamEmitter(); | ||
} | ||
$emitter->emit($response); | ||
} | ||
|
||
/** | ||
* Set the application. | ||
* | ||
* @param BaseApplication $app The application to set. | ||
* @return $this | ||
*/ | ||
public function setApp(BaseApplication $app) | ||
{ | ||
$this->app = $app; | ||
return $this; | ||
} | ||
|
||
/** | ||
* Get the current application. | ||
* | ||
* @return BaseApplication The application that will be run. | ||
*/ | ||
public function getApp() | ||
{ | ||
return $this->app; | ||
} | ||
|
||
/** | ||
* Set the runner | ||
* | ||
* @param \Cake\Http\Runner $runner The runner to use. | ||
* @return $this | ||
*/ | ||
public function setRunner(Runner $runner) | ||
{ | ||
$this->runner = $runner; | ||
return $this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
namespace Cake\Test\TestCase; | ||
|
||
use Cake\Core\Configure; | ||
use Cake\Http\BaseApplication; | ||
use Cake\Http\ServerRequestFactory; | ||
use Cake\TestSuite\TestCase; | ||
use Zend\Diactoros\Response; | ||
|
||
/** | ||
* Base application test. | ||
*/ | ||
class BaseApplicationTest extends TestCase | ||
{ | ||
/** | ||
* Setup | ||
* | ||
* @return void | ||
*/ | ||
public function setUp() | ||
{ | ||
parent::setUp(); | ||
Configure::write('App.namespace', 'TestApp'); | ||
} | ||
|
||
/** | ||
* Integration test for a simple controller. | ||
* | ||
* @return void | ||
*/ | ||
public function testInvoke() | ||
{ | ||
$next = function ($req, $res) { | ||
return $res; | ||
}; | ||
$response = new Response(); | ||
$request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/cakes']); | ||
$request = $request->withAttribute('params', [ | ||
'controller' => 'Cakes', | ||
'action' => 'index', | ||
'plugin' => null, | ||
'pass' => [] | ||
]); | ||
|
||
$path = dirname(dirname(__DIR__)); | ||
$app = $this->getMockForAbstractClass('Cake\Http\BaseApplication', [$path]); | ||
$result = $app($request, $response, $next); | ||
$this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $result); | ||
$this->assertEquals('Hello Jane', '' . $result->getBody()); | ||
} | ||
} |
Oops, something went wrong.