Server.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 3.3.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Http;
  16. use Cake\Core\HttpApplicationInterface;
  17. use Cake\Core\PluginApplicationInterface;
  18. use Cake\Event\EventDispatcherInterface;
  19. use Cake\Event\EventDispatcherTrait;
  20. use Cake\Event\EventManager;
  21. use InvalidArgumentException;
  22. use Psr\Http\Message\ResponseInterface;
  23. use Psr\Http\Message\ServerRequestInterface;
  24. use RuntimeException;
  25. use Zend\Diactoros\Response\EmitterInterface;
  26. /**
  27. * Runs an application invoking all the PSR7 middleware and the registered application.
  28. */
  29. class Server implements EventDispatcherInterface
  30. {
  31. /**
  32. * Alias methods away so we can implement proxying methods.
  33. */
  34. use EventDispatcherTrait {
  35. eventManager as private _eventManager;
  36. getEventManager as private _getEventManager;
  37. setEventManager as private _setEventManager;
  38. }
  39. /**
  40. * @var \Cake\Core\HttpApplicationInterface
  41. */
  42. protected $app;
  43. /**
  44. * @var \Cake\Http\Runner
  45. */
  46. protected $runner;
  47. /**
  48. * Constructor
  49. *
  50. * @param \Cake\Core\HttpApplicationInterface $app The application to use.
  51. */
  52. public function __construct(HttpApplicationInterface $app)
  53. {
  54. $this->app = $app;
  55. $this->setRunner(new Runner());
  56. }
  57. /**
  58. * Run the request/response through the Application and its middleware.
  59. *
  60. * This will invoke the following methods:
  61. *
  62. * - App->bootstrap() - Perform any bootstrapping logic for your application here.
  63. * - App->middleware() - Attach any application middleware here.
  64. * - Trigger the 'Server.buildMiddleware' event. You can use this to modify the
  65. * from event listeners.
  66. * - Run the middleware queue including the application.
  67. *
  68. * @param \Psr\Http\Message\ServerRequestInterface|null $request The request to use or null.
  69. * @param \Psr\Http\Message\ResponseInterface|null $response The response to use or null.
  70. * @return \Psr\Http\Message\ResponseInterface
  71. * @throws \RuntimeException When the application does not make a response.
  72. */
  73. public function run(ServerRequestInterface $request = null, ResponseInterface $response = null)
  74. {
  75. $this->bootstrap();
  76. $response = $response ?: new Response();
  77. $request = $request ?: ServerRequestFactory::fromGlobals();
  78. $middleware = $this->app->middleware(new MiddlewareQueue());
  79. if ($this->app instanceof PluginApplicationInterface) {
  80. $middleware = $this->app->pluginMiddleware($middleware);
  81. }
  82. if (!($middleware instanceof MiddlewareQueue)) {
  83. throw new RuntimeException('The application `middleware` method did not return a middleware queue.');
  84. }
  85. $this->dispatchEvent('Server.buildMiddleware', ['middleware' => $middleware]);
  86. $middleware->add($this->app);
  87. $response = $this->runner->run($middleware, $request, $response);
  88. if (!($response instanceof ResponseInterface)) {
  89. throw new RuntimeException(sprintf(
  90. 'Application did not create a response. Got "%s" instead.',
  91. is_object($response) ? get_class($response) : $response
  92. ));
  93. }
  94. return $response;
  95. }
  96. /**
  97. * Application bootstrap wrapper.
  98. *
  99. * Calls `bootstrap()` and `events()` if application implements `EventApplicationInterface`.
  100. * After the application is bootstrapped and events are attached, plugins are bootstrapped
  101. * and have their events attached.
  102. *
  103. * @return void
  104. */
  105. protected function bootstrap()
  106. {
  107. $this->app->bootstrap();
  108. if ($this->app instanceof PluginApplicationInterface) {
  109. $this->app->pluginBootstrap();
  110. }
  111. }
  112. /**
  113. * Emit the response using the PHP SAPI.
  114. *
  115. * @param \Psr\Http\Message\ResponseInterface $response The response to emit
  116. * @param \Zend\Diactoros\Response\EmitterInterface|null $emitter The emitter to use.
  117. * When null, a SAPI Stream Emitter will be used.
  118. * @return void
  119. */
  120. public function emit(ResponseInterface $response, EmitterInterface $emitter = null)
  121. {
  122. if (!$emitter) {
  123. $emitter = new ResponseEmitter();
  124. }
  125. $emitter->emit($response);
  126. }
  127. /**
  128. * Get the current application.
  129. *
  130. * @return \Cake\Core\HttpApplicationInterface The application that will be run.
  131. */
  132. public function getApp()
  133. {
  134. return $this->app;
  135. }
  136. /**
  137. * Set the runner
  138. *
  139. * @param \Cake\Http\Runner $runner The runner to use.
  140. * @return $this
  141. */
  142. public function setRunner(Runner $runner)
  143. {
  144. $this->runner = $runner;
  145. return $this;
  146. }
  147. /**
  148. * Get the application's event manager or the global one.
  149. *
  150. * @return \Cake\Event\EventManager
  151. */
  152. public function getEventManager()
  153. {
  154. if ($this->app instanceof PluginApplicationInterface) {
  155. return $this->app->getEventManager();
  156. }
  157. return EventManager::instance();
  158. }
  159. /**
  160. * Get/set the application's event manager.
  161. *
  162. * If the application does not support events and this method is used as
  163. * a setter, an exception will be raised.
  164. *
  165. * @param \Cake\Event\EventManager|null $events The event manager to set.
  166. * @return \Cake\Event\EventManager|$this
  167. * @deprecated 3.6.0 Will be removed in 4.0
  168. */
  169. public function eventManager(EventManager $events = null)
  170. {
  171. deprecationWarning('eventManager() is deprecated. Use getEventManager()/setEventManager() instead.');
  172. if ($events === null) {
  173. return $this->getEventManager();
  174. }
  175. return $this->setEventManager($events);
  176. }
  177. /**
  178. * Get/set the application's event manager.
  179. *
  180. * If the application does not support events and this method is used as
  181. * a setter, an exception will be raised.
  182. *
  183. * @param \Cake\Event\EventManager $events The event manager to set.
  184. * @return $this
  185. */
  186. public function setEventManager(EventManager $events)
  187. {
  188. if ($this->app instanceof PluginApplicationInterface) {
  189. $this->app->setEventManager($events);
  190. return $this;
  191. }
  192. throw new InvalidArgumentException('Cannot set the event manager, the application does not support events.');
  193. }
  194. }