| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- <?php
- // +----------------------------------------------------------------------
- // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
- // +----------------------------------------------------------------------
- // | Author: liu21st <liu21st@gmail.com>
- // +----------------------------------------------------------------------
- namespace think\worker;
- use RecursiveDirectoryIterator;
- use RecursiveIteratorIterator;
- use Workerman\Connection\TcpConnection;
- use Workerman\Lib\Timer;
- use Workerman\Protocols\Http as WorkerHttp;
- use Workerman\Worker;
- /**
- * Worker http server 命令行服务类
- */
- class Http extends Server
- {
- protected $app;
- protected $rootPath;
- protected $root;
- protected $appInit;
- protected $monitor;
- protected $lastMtime;
- /** @var array Mime mapping. */
- protected static $mimeTypeMap = [];
- /**
- * 架构函数
- * @access public
- * @param string $host 监听地址
- * @param int $port 监听端口
- * @param array $context 参数
- */
- public function __construct($host, $port, $context = [])
- {
- $this->worker = new Worker('http://' . $host . ':' . $port, $context);
- // 设置回调
- foreach ($this->event as $event) {
- if (method_exists($this, $event)) {
- $this->worker->$event = [$this, $event];
- }
- }
- }
- public function setRootPath($path)
- {
- $this->rootPath = $path;
- }
- public function appInit(\Closure $closure)
- {
- $this->appInit = $closure;
- }
- public function setRoot($path)
- {
- $this->root = $path;
- }
- public function setStaticOption($name, $value)
- {
- Worker::${$name} = $value;
- }
- public function setMonitor($interval = 2, $path = [])
- {
- $this->monitor['interval'] = $interval;
- $this->monitor['path'] = (array) $path;
- }
- /**
- * 设置参数
- * @access public
- * @param array $option 参数
- * @return void
- */
- public function option(array $option)
- {
- // 设置参数
- if (!empty($option)) {
- foreach ($option as $key => $val) {
- $this->worker->$key = $val;
- }
- }
- }
- /**
- * onWorkerStart 事件回调
- * @access public
- * @param \Workerman\Worker $worker
- * @return void
- */
- public function onWorkerStart($worker)
- {
- $this->initMimeTypeMap();
- $this->app = new Application($this->rootPath);
- if ($this->appInit) {
- call_user_func_array($this->appInit, [$this->app]);
- }
- $this->app->initialize();
- $this->lastMtime = time();
- $this->app->workerman = $worker;
- $this->app->bind([
- 'think\Cookie' => Cookie::class,
- ]);
- if (0 == $worker->id && $this->monitor) {
- $paths = $this->monitor['path'];
- $timer = $this->monitor['interval'] ?: 2;
- Timer::add($timer, function () use ($paths) {
- foreach ($paths as $path) {
- $dir = new RecursiveDirectoryIterator($path);
- $iterator = new RecursiveIteratorIterator($dir);
- foreach ($iterator as $file) {
- if (pathinfo($file, PATHINFO_EXTENSION) != 'php') {
- continue;
- }
- if ($this->lastMtime < $file->getMTime()) {
- echo '[update]' . $file . "\n";
- posix_kill(posix_getppid(), SIGUSR1);
- $this->lastMtime = $file->getMTime();
- return;
- }
- }
- }
- });
- }
- }
- /**
- * onMessage 事件回调
- * @access public
- * @param TcpConnection $connection
- * @param mixed $data
- * @return void
- */
- public function onMessage($connection, $data)
- {
- $uri = parse_url($_SERVER['REQUEST_URI']);
- $path = $uri['path'] ?? '/';
- $file = $this->root . $path;
- if (!is_file($file)) {
- $this->app->worker($connection, $data);
- } else {
- $this->sendFile($connection, $file);
- }
- }
- /**
- * 访问资源文件
- * @access protected
- * @param TcpConnection $connection
- * @param string $file 文件名
- * @return string
- */
- protected function sendFile($connection, $file)
- {
- $info = stat($file);
- $modifiyTime = $info ? date('D, d M Y H:i:s', $info['mtime']) . ' ' . date_default_timezone_get() : '';
- if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $info) {
- // Http 304.
- if ($modifiyTime === $_SERVER['HTTP_IF_MODIFIED_SINCE']) {
- // 304
- WorkerHttp::header('HTTP/1.1 304 Not Modified');
- // Send nothing but http headers..
- return $connection->close('');
- }
- }
- $mimeType = $this->getMimeType($file);
- WorkerHttp::header('HTTP/1.1 200 OK');
- WorkerHttp::header('Connection: keep-alive');
- if ($mimeType) {
- WorkerHttp::header('Content-Type: ' . $mimeType);
- } else {
- WorkerHttp::header('Content-Type: application/octet-stream');
- $fileinfo = pathinfo($file);
- $filename = $fileinfo['filename'] ?? '';
- WorkerHttp::header('Content-Disposition: attachment; filename="' . $filename . '"');
- }
- if ($modifiyTime) {
- WorkerHttp::header('Last-Modified: ' . $modifiyTime);
- }
- WorkerHttp::header('Content-Length: ' . filesize($file));
- ob_start();
- readfile($file);
- $content = ob_get_clean();
- return $connection->send($content);
- }
- /**
- * 获取文件类型信息
- * @access protected
- * @param string $filename 文件名
- * @return string
- */
- protected function getMimeType(string $filename)
- {
- $file_info = pathinfo($filename);
- $extension = $file_info['extension'] ?? '';
- if (isset(self::$mimeTypeMap[$extension])) {
- $mime = self::$mimeTypeMap[$extension];
- } else {
- $finfo = finfo_open(FILEINFO_MIME_TYPE);
- $mime = finfo_file($finfo, $filename);
- }
- return $mime;
- }
- /**
- * Init mime map.
- *
- * @return void
- * @throws \Exception
- */
- protected function initMimeTypeMap()
- {
- $mime_file = WorkerHttp::getMimeTypesFile();
- if (!is_file($mime_file)) {
- Worker::log("$mime_file mime.type file not fond");
- return;
- }
- $items = file($mime_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
- if (!is_array($items)) {
- Worker::log("get $mime_file mime.type content fail");
- return;
- }
- foreach ($items as $content) {
- if (preg_match("/\s*(\S+)\s+(\S.+)/", $content, $match)) {
- $mime_type = $match[1];
- $workerman_file_extension_var = $match[2];
- $workerman_file_extension_array = explode(' ', substr($workerman_file_extension_var, 0, -1));
- foreach ($workerman_file_extension_array as $workerman_file_extension) {
- self::$mimeTypeMap[$workerman_file_extension] = $mime_type;
- }
- }
- }
- }
- /**
- * 启动
- * @access public
- * @return void
- */
- public function start()
- {
- Worker::runAll();
- }
- /**
- * 停止
- * @access public
- * @return void
- */
- public function stop()
- {
- Worker::stopAll();
- }
- }
|