diff --git a/.gitignore b/.gitignore
index 297959a..516299c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,23 +1,8 @@
-/vendor/
-node_modules/
-npm-debug.log
-yarn-error.log
-
-# Laravel 4 specific
-bootstrap/compiled.php
-app/storage/
-
-# Laravel 5 & Lumen specific
-public/storage
-public/hot
-
-# Laravel 5 & Lumen specific with changed public path
-public_html/storage
-public_html/hot
-
-storage/*.key
+/runtime
+/.idea
+/.vscode
+/vendor
+*.log
.env
-Homestead.yaml
-Homestead.json
-/.vagrant
-.phpunit.result.cache
+/tests/tmp
+/tests/.phpunit.result.cache
diff --git a/app/controller/IndexController.php b/app/controller/IndexController.php
new file mode 100644
index 0000000..ef309f4
--- /dev/null
+++ b/app/controller/IndexController.php
@@ -0,0 +1,42 @@
+
+ * {
+ padding: 0;
+ margin: 0;
+ }
+ iframe {
+ border: none;
+ overflow: scroll;
+ }
+
+
+EOF;
+ }
+
+ public function view(Request $request)
+ {
+ return view('index/view', ['name' => 'webman']);
+ }
+
+ public function json(Request $request)
+ {
+ return json(['code' => 0, 'msg' => 'ok']);
+ }
+
+}
diff --git a/app/functions.php b/app/functions.php
new file mode 100644
index 0000000..5c9c58d
--- /dev/null
+++ b/app/functions.php
@@ -0,0 +1,4 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace app\middleware;
+
+use Webman\MiddlewareInterface;
+use Webman\Http\Response;
+use Webman\Http\Request;
+
+/**
+ * Class StaticFile
+ * @package app\middleware
+ */
+class StaticFile implements MiddlewareInterface
+{
+ public function process(Request $request, callable $handler): Response
+ {
+ // Access to files beginning with. Is prohibited
+ if (strpos($request->path(), '/.') !== false) {
+ return response('403 forbidden
', 403);
+ }
+ /** @var Response $response */
+ $response = $handler($request);
+ // Add cross domain HTTP header
+ /*$response->withHeaders([
+ 'Access-Control-Allow-Origin' => '*',
+ 'Access-Control-Allow-Credentials' => 'true',
+ ]);*/
+ return $response;
+ }
+}
diff --git a/app/model/Test.php b/app/model/Test.php
new file mode 100644
index 0000000..92d70e3
--- /dev/null
+++ b/app/model/Test.php
@@ -0,0 +1,29 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace app\process;
+
+use FilesystemIterator;
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
+use SplFileInfo;
+use Workerman\Timer;
+use Workerman\Worker;
+
+/**
+ * Class FileMonitor
+ * @package process
+ */
+class Monitor
+{
+ /**
+ * @var array
+ */
+ protected array $paths = [];
+
+ /**
+ * @var array
+ */
+ protected array $extensions = [];
+
+ /**
+ * @var array
+ */
+ protected array $loadedFiles = [];
+
+ /**
+ * @var int
+ */
+ protected int $ppid = 0;
+
+ /**
+ * Pause monitor
+ * @return void
+ */
+ public static function pause(): void
+ {
+ file_put_contents(static::lockFile(), time());
+ }
+
+ /**
+ * Resume monitor
+ * @return void
+ */
+ public static function resume(): void
+ {
+ clearstatcache();
+ if (is_file(static::lockFile())) {
+ unlink(static::lockFile());
+ }
+ }
+
+ /**
+ * Whether monitor is paused
+ * @return bool
+ */
+ public static function isPaused(): bool
+ {
+ clearstatcache();
+ return file_exists(static::lockFile());
+ }
+
+ /**
+ * Lock file
+ * @return string
+ */
+ protected static function lockFile(): string
+ {
+ return runtime_path('monitor.lock');
+ }
+
+ /**
+ * FileMonitor constructor.
+ * @param $monitorDir
+ * @param $monitorExtensions
+ * @param array $options
+ */
+ public function __construct($monitorDir, $monitorExtensions, array $options = [])
+ {
+ $this->ppid = function_exists('posix_getppid') ? posix_getppid() : 0;
+ static::resume();
+ $this->paths = (array)$monitorDir;
+ $this->extensions = $monitorExtensions;
+ foreach (get_included_files() as $index => $file) {
+ $this->loadedFiles[$file] = $index;
+ if (strpos($file, 'webman-framework/src/support/App.php')) {
+ break;
+ }
+ }
+ if (!Worker::getAllWorkers()) {
+ return;
+ }
+ $disableFunctions = explode(',', ini_get('disable_functions'));
+ if (in_array('exec', $disableFunctions, true)) {
+ echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n";
+ } else {
+ if ($options['enable_file_monitor'] ?? true) {
+ Timer::add(1, function () {
+ $this->checkAllFilesChange();
+ });
+ }
+ }
+
+ $memoryLimit = $this->getMemoryLimit($options['memory_limit'] ?? null);
+ if ($memoryLimit && ($options['enable_memory_monitor'] ?? true)) {
+ Timer::add(60, [$this, 'checkMemory'], [$memoryLimit]);
+ }
+ }
+
+ /**
+ * @param $monitorDir
+ * @return bool
+ */
+ public function checkFilesChange($monitorDir): bool
+ {
+ static $lastMtime, $tooManyFilesCheck;
+ if (!$lastMtime) {
+ $lastMtime = time();
+ }
+ clearstatcache();
+ if (!is_dir($monitorDir)) {
+ if (!is_file($monitorDir)) {
+ return false;
+ }
+ $iterator = [new SplFileInfo($monitorDir)];
+ } else {
+ // recursive traversal directory
+ $dirIterator = new RecursiveDirectoryIterator($monitorDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS);
+ $iterator = new RecursiveIteratorIterator($dirIterator);
+ }
+ $count = 0;
+ foreach ($iterator as $file) {
+ $count ++;
+ /** var SplFileInfo $file */
+ if (is_dir($file->getRealPath())) {
+ continue;
+ }
+ // check mtime
+ if (in_array($file->getExtension(), $this->extensions, true) && $lastMtime < $file->getMTime()) {
+ $lastMtime = $file->getMTime();
+ if (DIRECTORY_SEPARATOR === '/' && isset($this->loadedFiles[$file->getRealPath()])) {
+ echo "$file updated but cannot be reloaded because only auto-loaded files support reload.\n";
+ continue;
+ }
+ $var = 0;
+ exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var);
+ if ($var) {
+ continue;
+ }
+ // send SIGUSR1 signal to master process for reload
+ if (DIRECTORY_SEPARATOR === '/') {
+ if ($masterPid = $this->getMasterPid()) {
+ echo $file . " updated and reload\n";
+ posix_kill($masterPid, SIGUSR1);
+ } else {
+ echo "Master process has gone away and can not reload\n";
+ }
+ return true;
+ }
+ echo $file . " updated and reload\n";
+ return true;
+ }
+ }
+ if (!$tooManyFilesCheck && $count > 1000) {
+ echo "Monitor: There are too many files ($count files) in $monitorDir which makes file monitoring very slow\n";
+ $tooManyFilesCheck = 1;
+ }
+ return false;
+ }
+
+ /**
+ * @return int
+ */
+ public function getMasterPid(): int
+ {
+ if ($this->ppid === 0) {
+ return 0;
+ }
+ if (function_exists('posix_kill') && !posix_kill($this->ppid, 0)) {
+ echo "Master process has gone away\n";
+ return $this->ppid = 0;
+ }
+ if (PHP_OS_FAMILY !== 'Linux') {
+ return $this->ppid;
+ }
+ $cmdline = "/proc/$this->ppid/cmdline";
+ if (!is_readable($cmdline) || !($content = file_get_contents($cmdline)) || (!str_contains($content, 'WorkerMan') && !str_contains($content, 'php'))) {
+ // Process not exist
+ $this->ppid = 0;
+ }
+ return $this->ppid;
+ }
+
+ /**
+ * @return bool
+ */
+ public function checkAllFilesChange(): bool
+ {
+ if (static::isPaused()) {
+ return false;
+ }
+ foreach ($this->paths as $path) {
+ if ($this->checkFilesChange($path)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @param $memoryLimit
+ * @return void
+ */
+ public function checkMemory($memoryLimit): void
+ {
+ if (static::isPaused() || $memoryLimit <= 0) {
+ return;
+ }
+ $masterPid = $this->getMasterPid();
+ if ($masterPid <= 0) {
+ echo "Master process has gone away\n";
+ return;
+ }
+
+ $childrenFile = "/proc/$masterPid/task/$masterPid/children";
+ if (!is_file($childrenFile) || !($children = file_get_contents($childrenFile))) {
+ return;
+ }
+ foreach (explode(' ', $children) as $pid) {
+ $pid = (int)$pid;
+ $statusFile = "/proc/$pid/status";
+ if (!is_file($statusFile) || !($status = file_get_contents($statusFile))) {
+ continue;
+ }
+ $mem = 0;
+ if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) {
+ $mem = $match[1];
+ }
+ $mem = (int)($mem / 1024);
+ if ($mem >= $memoryLimit) {
+ posix_kill($pid, SIGINT);
+ }
+ }
+ }
+
+ /**
+ * Get memory limit
+ * @param $memoryLimit
+ * @return int
+ */
+ protected function getMemoryLimit($memoryLimit): int
+ {
+ if ($memoryLimit === 0) {
+ return 0;
+ }
+ $usePhpIni = false;
+ if (!$memoryLimit) {
+ $memoryLimit = ini_get('memory_limit');
+ $usePhpIni = true;
+ }
+
+ if ($memoryLimit == -1) {
+ return 0;
+ }
+ $unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]);
+ $memoryLimit = (int)$memoryLimit;
+ if ($unit === 'g') {
+ $memoryLimit = 1024 * $memoryLimit;
+ } else if ($unit === 'k') {
+ $memoryLimit = ($memoryLimit / 1024);
+ } else if ($unit === 'm') {
+ $memoryLimit = (int)($memoryLimit);
+ } else if ($unit === 't') {
+ $memoryLimit = (1024 * 1024 * $memoryLimit);
+ } else {
+ $memoryLimit = ($memoryLimit / (1024 * 1024));
+ }
+ if ($memoryLimit < 50) {
+ $memoryLimit = 50;
+ }
+ if ($usePhpIni) {
+ $memoryLimit = (0.8 * $memoryLimit);
+ }
+ return (int)$memoryLimit;
+ }
+
+}
diff --git a/app/view/index/view.html b/app/view/index/view.html
new file mode 100644
index 0000000..67ebb26
--- /dev/null
+++ b/app/view/index/view.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+ webman
+
+
+
+hello =htmlspecialchars($name)?>
+
+
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..d25c083
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,55 @@
+{
+ "name": "workerman/webman",
+ "type": "project",
+ "keywords": [
+ "high performance",
+ "http service"
+ ],
+ "homepage": "https://www.workerman.net",
+ "license": "MIT",
+ "description": "High performance HTTP Service Framework.",
+ "authors": [
+ {
+ "name": "walkor",
+ "email": "walkor@workerman.net",
+ "homepage": "https://www.workerman.net",
+ "role": "Developer"
+ }
+ ],
+ "support": {
+ "email": "walkor@workerman.net",
+ "issues": "https://github.com/walkor/webman/issues",
+ "forum": "https://wenda.workerman.net/",
+ "wiki": "https://workerman.net/doc/webman",
+ "source": "https://github.com/walkor/webman"
+ },
+ "require": {
+ "php": ">=8.1",
+ "workerman/webman-framework": "^2.1",
+ "monolog/monolog": "^2.0"
+ },
+ "suggest": {
+ "ext-event": "For better performance. "
+ },
+ "autoload": {
+ "psr-4": {
+ "": "./",
+ "app\\": "./app",
+ "App\\": "./app",
+ "app\\View\\Components\\": "./app/view/components"
+ }
+ },
+ "scripts": {
+ "post-package-install": [
+ "support\\Plugin::install"
+ ],
+ "post-package-update": [
+ "support\\Plugin::install"
+ ],
+ "pre-package-uninstall": [
+ "support\\Plugin::uninstall"
+ ]
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..36a3af6
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,499 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "691f538563ac6695008ddc51b7722c80",
+ "packages": [
+ {
+ "name": "monolog/monolog",
+ "version": "2.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "5cf826f2991858b54d5c3809bee745560a1042a7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5cf826f2991858b54d5c3809bee745560a1042a7",
+ "reference": "5cf826f2991858b54d5c3809bee745560a1042a7",
+ "shasum": "",
+ "mirrors": [
+ {
+ "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+ "preferred": true
+ }
+ ]
+ },
+ "require": {
+ "php": ">=7.2",
+ "psr/log": "^1.0.1 || ^2.0 || ^3.0"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "^2.4.9 || ^3.0",
+ "doctrine/couchdb": "~1.0@dev",
+ "elasticsearch/elasticsearch": "^7 || ^8",
+ "ext-json": "*",
+ "graylog2/gelf-php": "^1.4.2 || ^2@dev",
+ "guzzlehttp/guzzle": "^7.4",
+ "guzzlehttp/psr7": "^2.2",
+ "mongodb/mongodb": "^1.8",
+ "php-amqplib/php-amqplib": "~2.4 || ^3",
+ "phpspec/prophecy": "^1.15",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^8.5.38 || ^9.6.19",
+ "predis/predis": "^1.1 || ^2.0",
+ "rollbar/rollbar": "^1.3 || ^2 || ^3",
+ "ruflin/elastica": "^7",
+ "swiftmailer/swiftmailer": "^5.3|^6.0",
+ "symfony/mailer": "^5.4 || ^6",
+ "symfony/mime": "^5.4 || ^6"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
+ "ext-mbstring": "Allow to work properly with unicode symbols",
+ "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
+ "ext-openssl": "Required to send log messages using SSL",
+ "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Monolog\\": "src/Monolog"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "https://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/monolog/issues",
+ "source": "https://github.com/Seldaek/monolog/tree/2.10.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-11-12T12:43:37+00:00"
+ },
+ {
+ "name": "nikic/fast-route",
+ "version": "v1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/FastRoute.git",
+ "reference": "181d480e08d9476e61381e04a71b34dc0432e812"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812",
+ "reference": "181d480e08d9476e61381e04a71b34dc0432e812",
+ "shasum": "",
+ "mirrors": [
+ {
+ "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+ "preferred": true
+ }
+ ]
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35|~5.7"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "FastRoute\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov",
+ "email": "nikic@php.net"
+ }
+ ],
+ "description": "Fast request router for PHP",
+ "keywords": [
+ "router",
+ "routing"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/FastRoute/issues",
+ "source": "https://github.com/nikic/FastRoute/tree/master"
+ },
+ "time": "2018-02-13T20:26:39+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "shasum": "",
+ "mirrors": [
+ {
+ "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+ "preferred": true
+ }
+ ]
+ },
+ "require": {
+ "php": ">=7.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/2.0.2"
+ },
+ "time": "2021-11-05T16:47:00+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "79dff0b268932c640297f5208d6298f71855c03e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/79dff0b268932c640297f5208d6298f71855c03e",
+ "reference": "79dff0b268932c640297f5208d6298f71855c03e",
+ "shasum": "",
+ "mirrors": [
+ {
+ "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+ "preferred": true
+ }
+ ]
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.1"
+ },
+ "time": "2024-08-21T13:31:24+00:00"
+ },
+ {
+ "name": "workerman/coroutine",
+ "version": "v1.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/workerman-php/coroutine.git",
+ "reference": "df8fc428967d512a74a8a7d80355c1d40228c9fa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/workerman-php/coroutine/zipball/df8fc428967d512a74a8a7d80355c1d40228c9fa",
+ "reference": "df8fc428967d512a74a8a7d80355c1d40228c9fa",
+ "shasum": "",
+ "mirrors": [
+ {
+ "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+ "preferred": true
+ }
+ ]
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0",
+ "psr/log": "*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Workerman\\": "src",
+ "Workerman\\Coroutine\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Workerman coroutine",
+ "support": {
+ "issues": "https://github.com/workerman-php/coroutine/issues",
+ "source": "https://github.com/workerman-php/coroutine/tree/v1.1.3"
+ },
+ "time": "2025-02-17T03:34:21+00:00"
+ },
+ {
+ "name": "workerman/webman-framework",
+ "version": "v2.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/walkor/webman-framework.git",
+ "reference": "f803bd867f07bb0929faef060b59a19a44186bfc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/walkor/webman-framework/zipball/f803bd867f07bb0929faef060b59a19a44186bfc",
+ "reference": "f803bd867f07bb0929faef060b59a19a44186bfc",
+ "shasum": "",
+ "mirrors": [
+ {
+ "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+ "preferred": true
+ }
+ ]
+ },
+ "require": {
+ "ext-json": "*",
+ "nikic/fast-route": "^1.3",
+ "php": ">=8.1",
+ "psr/container": ">=1.0",
+ "psr/log": "^3.0",
+ "workerman/workerman": "^5.1 || dev-master"
+ },
+ "suggest": {
+ "ext-event": "For better performance. "
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "./src/support/helpers.php"
+ ],
+ "psr-4": {
+ "Webman\\": "./src",
+ "Support\\": "./src/support",
+ "support\\": "./src/support",
+ "Support\\View\\": "./src/support/view",
+ "Support\\Bootstrap\\": "./src/support/bootstrap",
+ "Support\\Exception\\": "./src/support/exception"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "walkor",
+ "email": "walkor@workerman.net",
+ "homepage": "https://www.workerman.net",
+ "role": "Developer"
+ }
+ ],
+ "description": "High performance HTTP Service Framework.",
+ "homepage": "https://www.workerman.net",
+ "keywords": [
+ "High Performance",
+ "http service"
+ ],
+ "support": {
+ "email": "walkor@workerman.net",
+ "forum": "https://wenda.workerman.net/",
+ "issues": "https://github.com/walkor/webman/issues",
+ "source": "https://github.com/walkor/webman-framework",
+ "wiki": "https://doc.workerman.net/"
+ },
+ "time": "2025-03-10T11:52:22+00:00"
+ },
+ {
+ "name": "workerman/workerman",
+ "version": "v5.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/walkor/workerman.git",
+ "reference": "5ce17bc71dfdad0e9eba8cd658342da793d2f581"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/walkor/workerman/zipball/5ce17bc71dfdad0e9eba8cd658342da793d2f581",
+ "reference": "5ce17bc71dfdad0e9eba8cd658342da793d2f581",
+ "shasum": "",
+ "mirrors": [
+ {
+ "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+ "preferred": true
+ }
+ ]
+ },
+ "require": {
+ "ext-json": "*",
+ "php": ">=8.1",
+ "workerman/coroutine": "^1.1 || dev-main"
+ },
+ "conflict": {
+ "ext-swow": "=8.1"
+ },
+ "platform-dev": [],
+ "plugin-api-version": "2.3.0"
+}
diff --git a/config/app.php b/config/app.php
new file mode 100644
index 0000000..f26e358
--- /dev/null
+++ b/config/app.php
@@ -0,0 +1,26 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use support\Request;
+
+return [
+ 'debug' => true,
+ 'error_reporting' => E_ALL,
+ 'default_timezone' => 'Asia/Shanghai',
+ 'request_class' => Request::class,
+ 'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public',
+ 'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime',
+ 'controller_suffix' => 'Controller',
+ 'controller_reuse' => false,
+];
diff --git a/config/autoload.php b/config/autoload.php
new file mode 100644
index 0000000..69a8135
--- /dev/null
+++ b/config/autoload.php
@@ -0,0 +1,21 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+ 'files' => [
+ base_path() . '/app/functions.php',
+ base_path() . '/support/Request.php',
+ base_path() . '/support/Response.php',
+ ]
+];
diff --git a/config/bootstrap.php b/config/bootstrap.php
new file mode 100644
index 0000000..95d2e87
--- /dev/null
+++ b/config/bootstrap.php
@@ -0,0 +1,17 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+ support\bootstrap\Session::class,
+];
diff --git a/config/container.php b/config/container.php
new file mode 100644
index 0000000..106b7b4
--- /dev/null
+++ b/config/container.php
@@ -0,0 +1,15 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return new Webman\Container;
\ No newline at end of file
diff --git a/config/dependence.php b/config/dependence.php
new file mode 100644
index 0000000..8e964ed
--- /dev/null
+++ b/config/dependence.php
@@ -0,0 +1,15 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [];
\ No newline at end of file
diff --git a/config/exception.php b/config/exception.php
new file mode 100644
index 0000000..f2aede3
--- /dev/null
+++ b/config/exception.php
@@ -0,0 +1,17 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+ '' => support\exception\Handler::class,
+];
\ No newline at end of file
diff --git a/config/log.php b/config/log.php
new file mode 100644
index 0000000..7f05de5
--- /dev/null
+++ b/config/log.php
@@ -0,0 +1,32 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+ 'default' => [
+ 'handlers' => [
+ [
+ 'class' => Monolog\Handler\RotatingFileHandler::class,
+ 'constructor' => [
+ runtime_path() . '/logs/webman.log',
+ 7, //$maxFiles
+ Monolog\Logger::DEBUG,
+ ],
+ 'formatter' => [
+ 'class' => Monolog\Formatter\LineFormatter::class,
+ 'constructor' => [null, 'Y-m-d H:i:s', true],
+ ],
+ ]
+ ],
+ ],
+];
diff --git a/config/middleware.php b/config/middleware.php
new file mode 100644
index 0000000..8e964ed
--- /dev/null
+++ b/config/middleware.php
@@ -0,0 +1,15 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [];
\ No newline at end of file
diff --git a/config/process.php b/config/process.php
new file mode 100644
index 0000000..892dc82
--- /dev/null
+++ b/config/process.php
@@ -0,0 +1,62 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use support\Log;
+use support\Request;
+use app\process\Http;
+
+global $argv;
+
+return [
+ 'webman' => [
+ 'handler' => Http::class,
+ 'listen' => 'http://0.0.0.0:8787',
+ 'count' => cpu_count() * 4,
+ 'user' => '',
+ 'group' => '',
+ 'reusePort' => false,
+ 'eventLoop' => '',
+ 'context' => [],
+ 'constructor' => [
+ 'requestClass' => Request::class,
+ 'logger' => Log::channel('default'),
+ 'appPath' => app_path(),
+ 'publicPath' => public_path()
+ ]
+ ],
+ // File update detection and automatic reload
+ 'monitor' => [
+ 'handler' => app\process\Monitor::class,
+ 'reloadable' => false,
+ 'constructor' => [
+ // Monitor these directories
+ 'monitorDir' => array_merge([
+ app_path(),
+ config_path(),
+ base_path() . '/process',
+ base_path() . '/support',
+ base_path() . '/resource',
+ base_path() . '/.env',
+ ], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')),
+ // Files with these suffixes will be monitored
+ 'monitorExtensions' => [
+ 'php', 'html', 'htm', 'env'
+ ],
+ 'options' => [
+ 'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/',
+ 'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
+ ]
+ ]
+ ]
+];
diff --git a/config/route.php b/config/route.php
new file mode 100644
index 0000000..a5064fc
--- /dev/null
+++ b/config/route.php
@@ -0,0 +1,21 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use Webman\Route;
+
+
+
+
+
+
diff --git a/config/server.php b/config/server.php
new file mode 100644
index 0000000..054d01f
--- /dev/null
+++ b/config/server.php
@@ -0,0 +1,23 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+ 'event_loop' => '',
+ 'stop_timeout' => 2,
+ 'pid_file' => runtime_path() . '/webman.pid',
+ 'status_file' => runtime_path() . '/webman.status',
+ 'stdout_file' => runtime_path() . '/logs/stdout.log',
+ 'log_file' => runtime_path() . '/logs/workerman.log',
+ 'max_package_size' => 10 * 1024 * 1024
+];
diff --git a/config/session.php b/config/session.php
new file mode 100644
index 0000000..043f8c4
--- /dev/null
+++ b/config/session.php
@@ -0,0 +1,65 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use Webman\Session\FileSessionHandler;
+use Webman\Session\RedisSessionHandler;
+use Webman\Session\RedisClusterSessionHandler;
+
+return [
+
+ 'type' => 'file', // or redis or redis_cluster
+
+ 'handler' => FileSessionHandler::class,
+
+ 'config' => [
+ 'file' => [
+ 'save_path' => runtime_path() . '/sessions',
+ ],
+ 'redis' => [
+ 'host' => '127.0.0.1',
+ 'port' => 6379,
+ 'auth' => '',
+ 'timeout' => 2,
+ 'database' => '',
+ 'prefix' => 'redis_session_',
+ ],
+ 'redis_cluster' => [
+ 'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
+ 'timeout' => 2,
+ 'auth' => '',
+ 'prefix' => 'redis_session_',
+ ]
+ ],
+
+ 'session_name' => 'PHPSID',
+
+ 'auto_update_timestamp' => false,
+
+ 'lifetime' => 7*24*60*60,
+
+ 'cookie_lifetime' => 365*24*60*60,
+
+ 'cookie_path' => '/',
+
+ 'domain' => '',
+
+ 'http_only' => true,
+
+ 'secure' => false,
+
+ 'same_site' => '',
+
+ 'gc_probability' => [1, 1000],
+
+];
diff --git a/config/static.php b/config/static.php
new file mode 100644
index 0000000..6313679
--- /dev/null
+++ b/config/static.php
@@ -0,0 +1,23 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+/**
+ * Static file settings
+ */
+return [
+ 'enable' => true,
+ 'middleware' => [ // Static file Middleware
+ //app\middleware\StaticFile::class,
+ ],
+];
\ No newline at end of file
diff --git a/config/translation.php b/config/translation.php
new file mode 100644
index 0000000..96589b2
--- /dev/null
+++ b/config/translation.php
@@ -0,0 +1,25 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+/**
+ * Multilingual configuration
+ */
+return [
+ // Default language
+ 'locale' => 'zh_CN',
+ // Fallback language
+ 'fallback_locale' => ['zh_CN', 'en'],
+ // Folder where language files are stored
+ 'path' => base_path() . '/resource/translations',
+];
\ No newline at end of file
diff --git a/config/view.php b/config/view.php
new file mode 100644
index 0000000..e3a7b85
--- /dev/null
+++ b/config/view.php
@@ -0,0 +1,22 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use support\view\Raw;
+use support\view\Twig;
+use support\view\Blade;
+use support\view\ThinkPHP;
+
+return [
+ 'handler' => Raw::class
+];
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..b9f722e
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/start.php b/start.php
new file mode 100644
index 0000000..41ad7ef
--- /dev/null
+++ b/start.php
@@ -0,0 +1,5 @@
+#!/usr/bin/env php
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace support;
+
+/**
+ * Class Request
+ * @package support
+ */
+class Request extends \Webman\Http\Request
+{
+
+}
\ No newline at end of file
diff --git a/support/Response.php b/support/Response.php
new file mode 100644
index 0000000..9bc4e1e
--- /dev/null
+++ b/support/Response.php
@@ -0,0 +1,24 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace support;
+
+/**
+ * Class Response
+ * @package support
+ */
+class Response extends \Webman\Http\Response
+{
+
+}
\ No newline at end of file
diff --git a/support/bootstrap.php b/support/bootstrap.php
new file mode 100644
index 0000000..d913def
--- /dev/null
+++ b/support/bootstrap.php
@@ -0,0 +1,139 @@
+
+ * @copyright walkor
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use Dotenv\Dotenv;
+use support\Log;
+use Webman\Bootstrap;
+use Webman\Config;
+use Webman\Middleware;
+use Webman\Route;
+use Webman\Util;
+use Workerman\Events\Select;
+use Workerman\Worker;
+
+$worker = $worker ?? null;
+
+if (empty(Worker::$eventLoopClass)) {
+ Worker::$eventLoopClass = Select::class;
+}
+
+set_error_handler(function ($level, $message, $file = '', $line = 0) {
+ if (error_reporting() & $level) {
+ throw new ErrorException($message, 0, $level, $file, $line);
+ }
+});
+
+if ($worker) {
+ register_shutdown_function(function ($startTime) {
+ if (time() - $startTime <= 0.1) {
+ sleep(1);
+ }
+ }, time());
+}
+
+if (class_exists('Dotenv\Dotenv') && file_exists(base_path(false) . '/.env')) {
+ if (method_exists('Dotenv\Dotenv', 'createUnsafeMutable')) {
+ Dotenv::createUnsafeMutable(base_path(false))->load();
+ } else {
+ Dotenv::createMutable(base_path(false))->load();
+ }
+}
+
+Config::clear();
+support\App::loadAllConfig(['route']);
+if ($timezone = config('app.default_timezone')) {
+ date_default_timezone_set($timezone);
+}
+
+foreach (config('autoload.files', []) as $file) {
+ include_once $file;
+}
+foreach (config('plugin', []) as $firm => $projects) {
+ foreach ($projects as $name => $project) {
+ if (!is_array($project)) {
+ continue;
+ }
+ foreach ($project['autoload']['files'] ?? [] as $file) {
+ include_once $file;
+ }
+ }
+ foreach ($projects['autoload']['files'] ?? [] as $file) {
+ include_once $file;
+ }
+}
+
+Middleware::load(config('middleware', []));
+foreach (config('plugin', []) as $firm => $projects) {
+ foreach ($projects as $name => $project) {
+ if (!is_array($project) || $name === 'static') {
+ continue;
+ }
+ Middleware::load($project['middleware'] ?? []);
+ }
+ Middleware::load($projects['middleware'] ?? [], $firm);
+ if ($staticMiddlewares = config("plugin.$firm.static.middleware")) {
+ Middleware::load(['__static__' => $staticMiddlewares], $firm);
+ }
+}
+Middleware::load(['__static__' => config('static.middleware', [])]);
+
+foreach (config('bootstrap', []) as $className) {
+ if (!class_exists($className)) {
+ $log = "Warning: Class $className setting in config/bootstrap.php not found\r\n";
+ echo $log;
+ Log::error($log);
+ continue;
+ }
+ /** @var Bootstrap $className */
+ $className::start($worker);
+}
+
+foreach (config('plugin', []) as $firm => $projects) {
+ foreach ($projects as $name => $project) {
+ if (!is_array($project)) {
+ continue;
+ }
+ foreach ($project['bootstrap'] ?? [] as $className) {
+ if (!class_exists($className)) {
+ $log = "Warning: Class $className setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
+ echo $log;
+ Log::error($log);
+ continue;
+ }
+ /** @var Bootstrap $className */
+ $className::start($worker);
+ }
+ }
+ foreach ($projects['bootstrap'] ?? [] as $className) {
+ /** @var string $className */
+ if (!class_exists($className)) {
+ $log = "Warning: Class $className setting in plugin/$firm/config/bootstrap.php not found\r\n";
+ echo $log;
+ Log::error($log);
+ continue;
+ }
+ /** @var Bootstrap $className */
+ $className::start($worker);
+ }
+}
+
+$directory = base_path() . '/plugin';
+$paths = [config_path()];
+foreach (Util::scanDir($directory) as $path) {
+ if (is_dir($path = "$path/config")) {
+ $paths[] = $path;
+ }
+}
+Route::load($paths);
+
diff --git a/windows.bat b/windows.bat
new file mode 100644
index 0000000..f07ce53
--- /dev/null
+++ b/windows.bat
@@ -0,0 +1,3 @@
+CHCP 65001
+php windows.php
+pause
\ No newline at end of file
diff --git a/windows.php b/windows.php
new file mode 100644
index 0000000..f37a72c
--- /dev/null
+++ b/windows.php
@@ -0,0 +1,136 @@
+load();
+ } else {
+ Dotenv::createMutable(base_path())->load();
+ }
+}
+
+App::loadAllConfig(['route']);
+
+$errorReporting = config('app.error_reporting');
+if (isset($errorReporting)) {
+ error_reporting($errorReporting);
+}
+
+$runtimeProcessPath = runtime_path() . DIRECTORY_SEPARATOR . '/windows';
+$paths = [
+ $runtimeProcessPath,
+ runtime_path('logs'),
+ runtime_path('views')
+];
+foreach ($paths as $path) {
+ if (!is_dir($path)) {
+ mkdir($path, 0777, true);
+ }
+}
+
+$processFiles = [];
+if (config('server.listen')) {
+ $processFiles[] = __DIR__ . DIRECTORY_SEPARATOR . 'start.php';
+}
+foreach (config('process', []) as $processName => $config) {
+ $processFiles[] = write_process_file($runtimeProcessPath, $processName, '');
+}
+
+foreach (config('plugin', []) as $firm => $projects) {
+ foreach ($projects as $name => $project) {
+ if (!is_array($project)) {
+ continue;
+ }
+ foreach ($project['process'] ?? [] as $processName => $config) {
+ $processFiles[] = write_process_file($runtimeProcessPath, $processName, "$firm.$name");
+ }
+ }
+ foreach ($projects['process'] ?? [] as $processName => $config) {
+ $processFiles[] = write_process_file($runtimeProcessPath, $processName, $firm);
+ }
+}
+
+function write_process_file($runtimeProcessPath, $processName, $firm): string
+{
+ $processParam = $firm ? "plugin.$firm.$processName" : $processName;
+ $configParam = $firm ? "config('plugin.$firm.process')['$processName']" : "config('process')['$processName']";
+ $fileContent = << true]);
+ if (!$resource) {
+ exit("Can not execute $cmd\r\n");
+ }
+ return $resource;
+}
+
+$resource = popen_processes($processFiles);
+echo "\r\n";
+while (1) {
+ sleep(1);
+ if (!empty($monitor) && $monitor->checkAllFilesChange()) {
+ $status = proc_get_status($resource);
+ $pid = $status['pid'];
+ shell_exec("taskkill /F /T /PID $pid");
+ proc_close($resource);
+ $resource = popen_processes($processFiles);
+ }
+}