/blog/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php

https://gitlab.com/zan_zan/laravel_sample · PHP · 294 lines · 138 code · 42 blank · 114 comment · 6 complexity · f352ebe56a40d7fe9c193361fd1580d4 MD5 · raw file

  1. <?php
  2. namespace Illuminate\Foundation\Http;
  3. use Exception;
  4. use Throwable;
  5. use RuntimeException;
  6. use Illuminate\Routing\Router;
  7. use Illuminate\Pipeline\Pipeline;
  8. use Illuminate\Support\Facades\Facade;
  9. use Illuminate\Contracts\Foundation\Application;
  10. use Illuminate\Contracts\Http\Kernel as KernelContract;
  11. use Symfony\Component\Debug\Exception\FatalThrowableError;
  12. class Kernel implements KernelContract
  13. {
  14. /**
  15. * The application implementation.
  16. *
  17. * @var \Illuminate\Contracts\Foundation\Application
  18. */
  19. protected $app;
  20. /**
  21. * The router instance.
  22. *
  23. * @var \Illuminate\Routing\Router
  24. */
  25. protected $router;
  26. /**
  27. * The bootstrap classes for the application.
  28. *
  29. * @var array
  30. */
  31. protected $bootstrappers = [
  32. 'Illuminate\Foundation\Bootstrap\DetectEnvironment',
  33. 'Illuminate\Foundation\Bootstrap\LoadConfiguration',
  34. 'Illuminate\Foundation\Bootstrap\ConfigureLogging',
  35. 'Illuminate\Foundation\Bootstrap\HandleExceptions',
  36. 'Illuminate\Foundation\Bootstrap\RegisterFacades',
  37. 'Illuminate\Foundation\Bootstrap\RegisterProviders',
  38. 'Illuminate\Foundation\Bootstrap\BootProviders',
  39. ];
  40. /**
  41. * The application's middleware stack.
  42. *
  43. * @var array
  44. */
  45. protected $middleware = [];
  46. /**
  47. * The application's route middleware.
  48. *
  49. * @var array
  50. */
  51. protected $routeMiddleware = [];
  52. /**
  53. * Create a new HTTP kernel instance.
  54. *
  55. * @param \Illuminate\Contracts\Foundation\Application $app
  56. * @param \Illuminate\Routing\Router $router
  57. * @return void
  58. */
  59. public function __construct(Application $app, Router $router)
  60. {
  61. $this->app = $app;
  62. $this->router = $router;
  63. foreach ($this->routeMiddleware as $key => $middleware) {
  64. $router->middleware($key, $middleware);
  65. }
  66. }
  67. /**
  68. * Handle an incoming HTTP request.
  69. *
  70. * @param \Illuminate\Http\Request $request
  71. * @return \Illuminate\Http\Response
  72. */
  73. public function handle($request)
  74. {
  75. try {
  76. $request->enableHttpMethodParameterOverride();
  77. $response = $this->sendRequestThroughRouter($request);
  78. } catch (Exception $e) {
  79. $this->reportException($e);
  80. $response = $this->renderException($request, $e);
  81. } catch (Throwable $e) {
  82. $e = new FatalThrowableError($e);
  83. $this->reportException($e);
  84. $response = $this->renderException($request, $e);
  85. }
  86. $this->app['events']->fire('kernel.handled', [$request, $response]);
  87. return $response;
  88. }
  89. /**
  90. * Send the given request through the middleware / router.
  91. *
  92. * @param \Illuminate\Http\Request $request
  93. * @return \Illuminate\Http\Response
  94. */
  95. protected function sendRequestThroughRouter($request)
  96. {
  97. $this->app->instance('request', $request);
  98. Facade::clearResolvedInstance('request');
  99. $this->bootstrap();
  100. return (new Pipeline($this->app))
  101. ->send($request)
  102. ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
  103. ->then($this->dispatchToRouter());
  104. }
  105. /**
  106. * Call the terminate method on any terminable middleware.
  107. *
  108. * @param \Illuminate\Http\Request $request
  109. * @param \Illuminate\Http\Response $response
  110. * @return void
  111. */
  112. public function terminate($request, $response)
  113. {
  114. $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
  115. $this->gatherRouteMiddlewares($request),
  116. $this->middleware
  117. );
  118. foreach ($middlewares as $middleware) {
  119. list($name, $parameters) = $this->parseMiddleware($middleware);
  120. $instance = $this->app->make($name);
  121. if (method_exists($instance, 'terminate')) {
  122. $instance->terminate($request, $response);
  123. }
  124. }
  125. $this->app->terminate();
  126. }
  127. /**
  128. * Gather the route middleware for the given request.
  129. *
  130. * @param \Illuminate\Http\Request $request
  131. * @return array
  132. */
  133. protected function gatherRouteMiddlewares($request)
  134. {
  135. if ($request->route()) {
  136. return $this->router->gatherRouteMiddlewares($request->route());
  137. }
  138. return [];
  139. }
  140. /**
  141. * Parse a middleware string to get the name and parameters.
  142. *
  143. * @param string $middleware
  144. * @return array
  145. */
  146. protected function parseMiddleware($middleware)
  147. {
  148. list($name, $parameters) = array_pad(explode(':', $middleware, 2), 2, []);
  149. if (is_string($parameters)) {
  150. $parameters = explode(',', $parameters);
  151. }
  152. return [$name, $parameters];
  153. }
  154. /**
  155. * Add a new middleware to beginning of the stack if it does not already exist.
  156. *
  157. * @param string $middleware
  158. * @return $this
  159. */
  160. public function prependMiddleware($middleware)
  161. {
  162. if (array_search($middleware, $this->middleware) === false) {
  163. array_unshift($this->middleware, $middleware);
  164. }
  165. return $this;
  166. }
  167. /**
  168. * Add a new middleware to end of the stack if it does not already exist.
  169. *
  170. * @param string $middleware
  171. * @return $this
  172. */
  173. public function pushMiddleware($middleware)
  174. {
  175. if (array_search($middleware, $this->middleware) === false) {
  176. $this->middleware[] = $middleware;
  177. }
  178. return $this;
  179. }
  180. /**
  181. * Bootstrap the application for HTTP requests.
  182. *
  183. * @return void
  184. */
  185. public function bootstrap()
  186. {
  187. if (!$this->app->hasBeenBootstrapped()) {
  188. $this->app->bootstrapWith($this->bootstrappers());
  189. }
  190. }
  191. /**
  192. * Get the route dispatcher callback.
  193. *
  194. * @return \Closure
  195. */
  196. protected function dispatchToRouter()
  197. {
  198. return function ($request) {
  199. $this->app->instance('request', $request);
  200. return $this->router->dispatch($request);
  201. };
  202. }
  203. /**
  204. * Determine if the kernel has a given middleware.
  205. *
  206. * @param string $middleware
  207. * @return bool
  208. */
  209. public function hasMiddleware($middleware)
  210. {
  211. return array_key_exists($middleware, array_flip($this->middleware));
  212. }
  213. /**
  214. * Get the bootstrap classes for the application.
  215. *
  216. * @return array
  217. */
  218. protected function bootstrappers()
  219. {
  220. return $this->bootstrappers;
  221. }
  222. /**
  223. * Report the exception to the exception handler.
  224. *
  225. * @param \Exception $e
  226. * @return void
  227. */
  228. protected function reportException(Exception $e)
  229. {
  230. $this->app['Illuminate\Contracts\Debug\ExceptionHandler']->report($e);
  231. }
  232. /**
  233. * Render the exception to a response.
  234. *
  235. * @param \Illuminate\Http\Request $request
  236. * @param \Exception $e
  237. * @return \Symfony\Component\HttpFoundation\Response
  238. */
  239. protected function renderException($request, Exception $e)
  240. {
  241. return $this->app['Illuminate\Contracts\Debug\ExceptionHandler']->render($request, $e);
  242. }
  243. /**
  244. * Get the Laravel application instance.
  245. *
  246. * @return \Illuminate\Contracts\Foundation\Application
  247. */
  248. public function getApplication()
  249. {
  250. return $this->app;
  251. }
  252. }