Http.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types = 1);
  12. namespace think;
  13. use think\event\HttpEnd;
  14. use think\event\HttpRun;
  15. use think\event\RouteLoaded;
  16. use think\exception\Handle;
  17. use Throwable;
  18. /**
  19. * Web应用管理类
  20. * @package think
  21. */
  22. class Http
  23. {
  24. /**
  25. * @var App
  26. */
  27. protected $app;
  28. /**
  29. * 应用名称
  30. * @var string
  31. */
  32. protected $name;
  33. /**
  34. * 应用路径
  35. * @var string
  36. */
  37. protected $path;
  38. /**
  39. * 路由路径
  40. * @var string
  41. */
  42. protected $routePath;
  43. /**
  44. * 是否绑定应用
  45. * @var bool
  46. */
  47. protected $isBind = false;
  48. public function __construct(App $app)
  49. {
  50. $this->app = $app;
  51. $this->routePath = $this->app->getRootPath() . 'route' . DIRECTORY_SEPARATOR;
  52. }
  53. /**
  54. * 设置应用名称
  55. * @access public
  56. * @param string $name 应用名称
  57. * @return $this
  58. */
  59. public function name(string $name)
  60. {
  61. $this->name = $name;
  62. return $this;
  63. }
  64. /**
  65. * 获取应用名称
  66. * @access public
  67. * @return string
  68. */
  69. public function getName(): string
  70. {
  71. return $this->name ?: '';
  72. }
  73. /**
  74. * 设置应用目录
  75. * @access public
  76. * @param string $path 应用目录
  77. * @return $this
  78. */
  79. public function path(string $path)
  80. {
  81. if (substr($path, -1) != DIRECTORY_SEPARATOR) {
  82. $path .= DIRECTORY_SEPARATOR;
  83. }
  84. $this->path = $path;
  85. return $this;
  86. }
  87. /**
  88. * 获取应用路径
  89. * @access public
  90. * @return string
  91. */
  92. public function getPath(): string
  93. {
  94. return $this->path ?: '';
  95. }
  96. /**
  97. * 获取路由目录
  98. * @access public
  99. * @return string
  100. */
  101. public function getRoutePath(): string
  102. {
  103. return $this->routePath;
  104. }
  105. /**
  106. * 设置路由目录
  107. * @access public
  108. * @param string $path 路由定义目录
  109. */
  110. public function setRoutePath(string $path): void
  111. {
  112. $this->routePath = $path;
  113. }
  114. /**
  115. * 设置应用绑定
  116. * @access public
  117. * @param bool $bind 是否绑定
  118. * @return $this
  119. */
  120. public function setBind(bool $bind = true)
  121. {
  122. $this->isBind = $bind;
  123. return $this;
  124. }
  125. /**
  126. * 是否绑定应用
  127. * @access public
  128. * @return bool
  129. */
  130. public function isBind(): bool
  131. {
  132. return $this->isBind;
  133. }
  134. /**
  135. * 执行应用程序
  136. * @access public
  137. * @param Request|null $request
  138. * @return Response
  139. */
  140. public function run(Request $request = null): Response
  141. {
  142. //初始化
  143. $this->initialize();
  144. //自动创建request对象
  145. $request = $request ?? $this->app->make('request', [], true);
  146. $this->app->instance('request', $request);
  147. try {
  148. $response = $this->runWithRequest($request);
  149. } catch (Throwable $e) {
  150. $this->reportException($e);
  151. $response = $this->renderException($request, $e);
  152. }
  153. return $response;
  154. }
  155. /**
  156. * 初始化
  157. */
  158. protected function initialize()
  159. {
  160. if (!$this->app->initialized()) {
  161. $this->app->initialize();
  162. }
  163. }
  164. /**
  165. * 执行应用程序
  166. * @param Request $request
  167. * @return mixed
  168. */
  169. protected function runWithRequest(Request $request)
  170. {
  171. // 加载全局中间件
  172. $this->loadMiddleware();
  173. // 监听HttpRun
  174. $this->app->event->trigger(HttpRun::class);
  175. return $this->app->middleware->pipeline()
  176. ->send($request)
  177. ->then(function ($request) {
  178. return $this->dispatchToRoute($request);
  179. });
  180. }
  181. protected function dispatchToRoute($request)
  182. {
  183. $withRoute = $this->app->config->get('app.with_route', true) ? function () {
  184. $this->loadRoutes();
  185. } : null;
  186. return $this->app->route->dispatch($request, $withRoute);
  187. }
  188. /**
  189. * 加载全局中间件
  190. */
  191. protected function loadMiddleware(): void
  192. {
  193. if (is_file($this->app->getBasePath() . 'middleware.php')) {
  194. $this->app->middleware->import(include $this->app->getBasePath() . 'middleware.php');
  195. }
  196. }
  197. /**
  198. * 加载路由
  199. * @access protected
  200. * @return void
  201. */
  202. protected function loadRoutes(): void
  203. {
  204. // 加载路由定义
  205. $routePath = $this->getRoutePath();
  206. if (is_dir($routePath)) {
  207. $files = glob($routePath . '*.php');
  208. foreach ($files as $file) {
  209. include $file;
  210. }
  211. }
  212. $this->app->event->trigger(RouteLoaded::class);
  213. }
  214. /**
  215. * Report the exception to the exception handler.
  216. *
  217. * @param Throwable $e
  218. * @return void
  219. */
  220. protected function reportException(Throwable $e)
  221. {
  222. $this->app->make(Handle::class)->report($e);
  223. }
  224. /**
  225. * Render the exception to a response.
  226. *
  227. * @param Request $request
  228. * @param Throwable $e
  229. * @return Response
  230. */
  231. protected function renderException($request, Throwable $e)
  232. {
  233. return $this->app->make(Handle::class)->render($request, $e);
  234. }
  235. /**
  236. * HttpEnd
  237. * @param Response $response
  238. * @return void
  239. */
  240. public function end(Response $response): void
  241. {
  242. $this->app->event->trigger(HttpEnd::class, $response);
  243. //执行中间件
  244. $this->app->middleware->end($response);
  245. // 写入日志
  246. $this->app->log->save();
  247. }
  248. }