diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e846cb4e..d610f15f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,57 +1,111 @@
-name: PHPUnit
+name: PHPUnit for MineAdmin
-on: [ push, pull_request ]
-
-env:
- SWOOLE_VERSION: '5.1.1'
- SWOW_VERSION: 'develop'
+on:
+ push:
+ pull_request:
+ schedule:
+ - cron: '0 2 * * *'
jobs:
- ci:
- name: Test PHP ${{ matrix.php-version }} on ${{ matrix.engine }}
+ cs-fix:
+ name: PHP CS Fix on PHP${{ matrix.php }} ${{ matrix.swoole }}
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ os: [ ubuntu-latest ]
+ php: [ '8.1','8.2','8.3' ]
+ swoole: [ 'swoole']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ tools: php-cs-fixer
+ extensions: redis, pdo, pdo_mysql, bcmath, ${{ matrix.swoole }}
+ - name: Setup Packages
+ run: composer update -oW
+ - name: Run CS Fix
+ run: |
+ vendor/bin/php-cs-fixer fix src --dry-run --diff
+ vendor/bin/php-cs-fixer fix src --dry-run --diff
+ tests:
+ needs: cs-fix
+ name: Test on PHP${{ matrix.php-version }} Swoole-${{ matrix.sw-version }}
runs-on: "${{ matrix.os }}"
strategy:
matrix:
os: [ ubuntu-latest ]
- php-version: ['8.1','8.2','8.3' ]
- engine: [ 'swoole' ]
- max-parallel: 5
- services:
- redis:
- image: redis
- ports:
- - "6379:6379"
+ php-version: [ '8.3', '8.2', '8.1' ]
+ sw-version: [ 'v5.0.3', 'v5.1.2', 'master' ]
+ exclude:
+ - php-version: '8.3'
+ sw-version: 'v5.0.3'
+ max-parallel: 20
+ fail-fast: false
+ env:
+ SW_VERSION: ${{ matrix.sw-version }}
+ MYSQL_VERSION: '8.0'
+ PGSQL_VERSION: '14'
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
+ - name: Upgrade
+ run: |
+ sudo apt-get clean
+ sudo apt-get update
+ sudo apt-get upgrade -f
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: phpize
+ extensions: redis, pdo, pdo_mysql, bcmath
ini-values: opcache.enable_cli=0
- coverage: none
- name: Setup Swoole
- if: ${{ matrix.engine == 'swoole' }}
run: |
- cd /tmp
- sudo apt-get update
- sudo apt-get install libcurl4-openssl-dev
- wget https://github.com/swoole/swoole-src/archive/v${SWOOLE_VERSION}.tar.gz -O swoole.tar.gz
+ sudo apt-get install libcurl4-openssl-dev libc-ares-dev libpq-dev
+ wget https://github.com/swoole/swoole-src/archive/${SW_VERSION}.tar.gz -O swoole.tar.gz
mkdir -p swoole
tar -xf swoole.tar.gz -C swoole --strip-components=1
rm swoole.tar.gz
cd swoole
phpize
- ./configure --enable-openssl --enable-http2 --enable-swoole-curl --enable-swoole-json
+ ./configure --enable-openssl --enable-swoole-curl --enable-cares --enable-swoole-pgsql --enable-brotli
make -j$(nproc)
sudo make install
sudo sh -c "echo extension=swoole > /etc/php/${{ matrix.php-version }}/cli/conf.d/swoole.ini"
+ sudo sh -c "echo swoole.use_shortname='Off' >> /etc/php/${{ matrix.php-version }}/cli/conf.d/swoole.ini"
php --ri swoole
- name: Setup Packages
- run: composer update -o --no-scripts
- - name: Run Test Cases
+ run: ./.travis/requirement.install.sh
+ - name: Run PHPStan
+ run: ./.travis/run.check.sh
+ - name: Setup Services
+ run: ./.travis/setup.services.sh
+ - name: Setup Mysql
+ run: export TRAVIS_BUILD_DIR=$(pwd) && bash ./.travis/setup.mysql.sh
+ - name: Setup PostgreSQL
+ run: export TRAVIS_BUILD_DIR=$(pwd) && bash ./.travis/setup.pgsql.sh
+ - name: Run Scripts Before Test
+ run: cp .travis/.env.example .env
+ - name: Print PHP Environments
run: |
- vendor/bin/php-cs-fixer fix --dry-run # cs-fixer 格式化代码
- composer analyse # phpstan 静态代码分析
- composer test # phpunit
\ No newline at end of file
+ php -i
+ php -m
+ - name: Run Test Cases
+ env:
+ DB_DRIVER: mysql
+ DB_HOST: 127.0.0.1
+ DB_DATABASE: mineadmin
+ run: ./.travis/run.test.sh
+# - name: Run PgSql Test Cases
+# env:
+# DB_DRIVER: pgsql
+# DB_HOST: 127.0.0.1
+# DB_PORT: 5432
+# DB_USERNAME: postgres
+# DB_PASSWORD: postgres
+# DB_CHARSET: utf8
+# DB_DATABASE: mineadmin
+# run: ./.travis/run.test.sh
\ No newline at end of file
diff --git a/.travis/.env.example b/.travis/.env.example
new file mode 100755
index 00000000..62497b5a
--- /dev/null
+++ b/.travis/.env.example
@@ -0,0 +1,14 @@
+APP_NAME=mineadmin
+APP_ENV=dev
+APP_DEBUG=true
+SUPER_ADMIN = 1000
+ADMIN_ROLE = 1000
+CONSOLE_SQL = false
+AMQP_HOST = 127.0.0.1
+AMQP_PORT = 5672
+AMQP_USER = mineadmin
+AMQP_PASSWORD = mineadmin
+AMQP_VHOST = /
+AMQP_ENABLE = false
+JWT_SECRET="mGlQxdNYoXIzVI0OkqQMaW07TpP94NUcjklspzEY6jXVeSparSQQ70kjlodwov2oINKluPuxgS7uetxaIJof4A=="
+JWT_API_SECRET="HLbcdGtYle+H0b18fLSaSdXrj/sSYoFfDMW0zqF/wf0ZgS0HxlqVzoQL2ocNLTsgP+v9EbyOoGghv94A2cGhkg=="
diff --git a/.travis/ci.ini b/.travis/ci.ini
new file mode 100755
index 00000000..9c87bafa
--- /dev/null
+++ b/.travis/ci.ini
@@ -0,0 +1,8 @@
+[opcache]
+opcache.enable_cli=1
+
+[redis]
+extension = "redis.so"
+
+[swoole]
+extension = "swoole.so"
\ No newline at end of file
diff --git a/.travis/requirement.install.sh b/.travis/requirement.install.sh
new file mode 100755
index 00000000..8fc41319
--- /dev/null
+++ b/.travis/requirement.install.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env sh
+
+set -e
+
+set -x
+
+composer install
+
+php ./.travis/run.replace.php
\ No newline at end of file
diff --git a/.travis/run.check.sh b/.travis/run.check.sh
new file mode 100755
index 00000000..ab17f206
--- /dev/null
+++ b/.travis/run.check.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -e
+
+composer analyse src
\ No newline at end of file
diff --git a/.travis/run.code-coverage.sh b/.travis/run.code-coverage.sh
new file mode 100755
index 00000000..7b6127ae
--- /dev/null
+++ b/.travis/run.code-coverage.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+set -e
+php bin/hyperf.php migrate --path=app/Setting/Database/Migrations
+
+php bin/hyperf.php migrate --path=app/System/Database/Migrations
+
+php bin/hyperf.php db:seed --path=app/Setting/Database/Seeders
+
+php bin/hyperf.php db:seed --path=app/System/Database/Seeders
+
+php bin/hyperf.php mine:update
+
+composer coverage
\ No newline at end of file
diff --git a/.travis/run.replace.php b/.travis/run.replace.php
new file mode 100755
index 00000000..b9f32317
--- /dev/null
+++ b/.travis/run.replace.php
@@ -0,0 +1,15 @@
+ ~/.pgpass
+chmod 600 ~/.pgpass
+
+docker exec postgres psql -d postgres -U postgres -c "create database mineadmin"
+
+echo -e "Done\n"
+
+wait
\ No newline at end of file
diff --git a/.travis/setup.services.sh b/.travis/setup.services.sh
new file mode 100755
index 00000000..0171ef84
--- /dev/null
+++ b/.travis/setup.services.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+docker run --name mysql -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=true -d mysql:${MYSQL_VERSION} --bind-address=0.0.0.0 --default-authentication-plugin=mysql_native_password &
+docker run --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=postgres -d postgres:${PGSQL_VERSION} &
+docker run --name redis -p 6379:6379 -d redis &
+docker run -d --restart=always --name rabbitmq -e RABBITMQ_DEFAULT_USER=mineadmin -e RABBITMQ_DEFAULT_PASS=123456 -p 4369:4369 -p 5672:5672 -p 15672:15672 -p 25672:25672 rabbitmq:management-alpine &
+wait
+sleep 10
+docker ps -a
\ No newline at end of file
diff --git a/CHANGELOG-2.0.md b/CHANGELOG-2.0.md
new file mode 100644
index 00000000..8c2fd6cc
--- /dev/null
+++ b/CHANGELOG-2.0.md
@@ -0,0 +1,7 @@
+# v2.0 - TBD
+
+# v2.0.0-RC 25 March 2024
+
+## Added
+
+- [#53](https://github.com/mineadmin/components/pull/53) Splitting components http-server
\ No newline at end of file
diff --git a/CHANGELOG-2.0.zh_CN.md b/CHANGELOG-2.0.zh_CN.md
new file mode 100644
index 00000000..38ff172e
--- /dev/null
+++ b/CHANGELOG-2.0.zh_CN.md
@@ -0,0 +1,7 @@
+# v2.0 - TBD
+
+# v2.0.0-RC 2024年3月25日
+
+## Added
+
+- [#53](https://github.com/mineadmin/components/pull/53) 拆分组件 http-server
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..04a43bcd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+# 项目介绍
+
+
+
+
+
+ 官网 |
+ 文档 |
+ 演示 |
+ Hyperf官方文档
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 0f24766f..1fc3cca4 100644
--- a/composer.json
+++ b/composer.json
@@ -19,7 +19,8 @@
"Mine\\Helper\\": "src/mine-helpers/src",
"Mine\\Generator\\": "src/mine-generator/src",
"Xmo\\AppStore\\": "src/app-store/src",
- "Mine\\NextCoreX\\": "src/next-core-x/src"
+ "Mine\\NextCoreX\\": "src/next-core-x/src",
+ "Mine\\HttpServer\\": "src/HttpServer/src"
},
"files": [
"src/mine-helpers/src/functions.php"
@@ -30,7 +31,8 @@
"Mine\\Tests\\": "tests",
"Xmo\\AppStore\\Tests\\": "src/app-store/tests",
"Xmo\\MineCore\\Tests\\": "src/mine-core/tests",
- "Mine\\NextCoreX\\Tests\\": "src/next-core-x/tests"
+ "Mine\\NextCoreX\\Tests\\": "src/next-core-x/tests",
+ "Mine\\HttpServer\\Tests\\": "src/HttpServer/tests"
}
},
"authors": [
@@ -54,7 +56,8 @@
"xmo/mine-helpers": "*",
"xmo/mine-genertor": "*",
"xmo/app-store": "*",
- "mine/next-core-x": "*"
+ "mine/next-core-x": "*",
+ "mineadmin/http-server": "*"
},
"require": {
"php": ">=8.1",
diff --git a/phpstan.neon b/phpstan.neon
index e0bd1d0a..27a0467d 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -17,6 +17,7 @@ parameters:
- src/mine-core/tests/*
- src/tests/
- src/app-store/test/
+ - src/httpServer/tests/
ignoreErrors:
- '#Unsafe usage of new static\(\)#'
- '#Call to static method find\(\) on an unknown class#'
diff --git a/phpunit.xml b/phpunit.xml
index dc91c4e7..4d219de5 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -3,18 +3,11 @@
+ ./src/HttpServer/tests
./src/app-store/tests
./src/mine-core/tests
./src/next-core-x/tests
./tests
-
-
- ./src/app-store/tests
- ./src/mine-core/tests
- ./src/next-core-x/tests
- ./tests
-
-
diff --git a/src/HttpServer/.github/workflows/close-pull-request.yml b/src/HttpServer/.github/workflows/close-pull-request.yml
new file mode 100644
index 00000000..c8182b84
--- /dev/null
+++ b/src/HttpServer/.github/workflows/close-pull-request.yml
@@ -0,0 +1,13 @@
+name: Close Pull Request
+
+on:
+ pull_request_target:
+ types: [ opened ]
+
+jobs:
+ run:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: superbrothers/close-pull-request@v3
+ with:
+ comment: "Hi, this is a READ-ONLY repository, please submit your PR on the https://github.com/mineadmin/components repository.
This Pull Request will close automatically.
Thanks! "
\ No newline at end of file
diff --git a/src/HttpServer/.github/workflows/release.yml b/src/HttpServer/.github/workflows/release.yml
new file mode 100644
index 00000000..2fc8404b
--- /dev/null
+++ b/src/HttpServer/.github/workflows/release.yml
@@ -0,0 +1,24 @@
+on:
+ push:
+ tags:
+ - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
+
+name: Release
+
+jobs:
+ release:
+ name: Release
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ - name: Create Release
+ id: create_release
+ uses: actions/create-release@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ github.ref }}
+ release_name: Release ${{ github.ref }}
+ draft: false
+ prerelease: false
\ No newline at end of file
diff --git a/src/HttpServer/IdeHelpers/RequestIde.php b/src/HttpServer/IdeHelpers/RequestIde.php
new file mode 100644
index 00000000..e824579d
--- /dev/null
+++ b/src/HttpServer/IdeHelpers/RequestIde.php
@@ -0,0 +1,31 @@
+=8.1",
+ "hyperf/http-server": "^3.1",
+ "hyperf/validation": "^3.1",
+ "hyperf/http-message": "^3.1",
+ "ramsey/uuid": "^4.7",
+ "hyperf/translation": "^3.1"
+ },
+ "autoload": {
+ "psr-4": {
+ "Mine\\HttpServer\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Mine\\HttpServer\\Tests\\": "tests/"
+ }
+ },
+ "extra": {
+ "hyperf": {
+ "config": "Mine\\HttpServer\\ConfigProvider"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/HttpServer/publish/languages/en/result.php b/src/HttpServer/publish/languages/en/result.php
new file mode 100644
index 00000000..eeea95a3
--- /dev/null
+++ b/src/HttpServer/publish/languages/en/result.php
@@ -0,0 +1,44 @@
+ 'Request success',
+ 'failed' => 'Request failed',
+ 'token' => [
+ 'expired' => 'TOKEN expired or does not exist',
+ ],
+ 'validate' => [
+ 'failed' => 'Data validation failed',
+ ],
+ 'no_permission' => 'No permission',
+ 'no_data' => 'No data',
+ 'normal_status' => 'Normal status abnormal code',
+ 'no_user' => 'User does not exist',
+ 'password_error' => 'Wrong password',
+ 'user_ban' => 'User is banned',
+ 'method_not_allow' => 'The address uses an unacceptable access method',
+ 'not_found' => 'Resource does not exist',
+ 'interface_exception' => 'Interface exception',
+ 'resource_stop' => 'Resource is disabled',
+ 'app_ban' => 'APP is disabled',
+ 'api_auth_exception' => 'Interface authentication exception',
+ 'api_auth_fail' => 'Interface authentication failed',
+ 'api_unbind_app' => 'The interface is not bound to the application',
+ 'api_app_id_missing' => 'Missing app_id',
+ 'api_app_secret_missing' => 'Missing APP SECRET',
+ 'api_access_token_missing' => 'Missing access token in complex mode',
+ 'api_params_error' => 'Parameter error in complex mode ACCESS TOKEN',
+ 'api_sign_missing' => 'Missing signature',
+ 'api_sign_error' => 'Signature error',
+ 'api_identity_missing' => 'Missing identity in simplified mode',
+ 'api_identity_error' => 'Identity error in simplified mode',
+ 'api_verify_pass' => 'API verification passed',
+];
diff --git a/src/HttpServer/publish/languages/zh_CN/result.php b/src/HttpServer/publish/languages/zh_CN/result.php
new file mode 100644
index 00000000..7df488c0
--- /dev/null
+++ b/src/HttpServer/publish/languages/zh_CN/result.php
@@ -0,0 +1,44 @@
+ '请求成功',
+ 'failed' => '请求失败',
+ 'token' => [
+ 'expired' => 'TOKEN过期、不存在',
+ ],
+ 'validate' => [
+ 'failed' => '数据验证失败',
+ ],
+ 'no_permission' => '没有权限',
+ 'no_data' => '没有数据',
+ 'normal_status' => '正常状态异常代码',
+ 'no_user' => '用户不存在',
+ 'password_error' => '密码错误',
+ 'user_ban' => '用户被禁',
+ 'method_not_allow' => '地址使用了不允许的访问方法',
+ 'not_found' => '资源不存在',
+ 'interface_exception' => '接口异常',
+ 'resource_stop' => '资源被停用',
+ 'app_ban' => 'APP被停用',
+ 'api_auth_exception' => '接口鉴权异常',
+ 'api_auth_fail' => '接口鉴权失败',
+ 'api_unbind_app' => '接口未被该应用绑定',
+ 'api_app_id_missing' => '缺少 app_id',
+ 'api_app_secret_missing' => '缺少APP SECRET',
+ 'api_access_token_missing' => '缺少复杂模式 ACCESS TOKEN',
+ 'api_params_error' => '复杂模式 ACCESS TOKEN 参数错误',
+ 'api_sign_missing' => '缺少签名',
+ 'api_sign_error' => '签名错误',
+ 'api_identity_missing' => '缺少简易模式 identity',
+ 'api_identity_error' => '简易模式 identity 错误',
+ 'api_verify_pass' => 'API验证通过',
+];
diff --git a/src/HttpServer/src/Config.php b/src/HttpServer/src/Config.php
new file mode 100644
index 00000000..679ca585
--- /dev/null
+++ b/src/HttpServer/src/Config.php
@@ -0,0 +1,29 @@
+config->get(self::PREFIX . '.' . $key, $default);
+ }
+}
diff --git a/src/HttpServer/src/ConfigProvider.php b/src/HttpServer/src/ConfigProvider.php
new file mode 100644
index 00000000..d07dbbbc
--- /dev/null
+++ b/src/HttpServer/src/ConfigProvider.php
@@ -0,0 +1,58 @@
+ [
+ 'scan' => [
+ 'paths' => [
+ __DIR__,
+ ],
+ ],
+ ],
+ // 默认 Command 的定义,合并到 Hyperf\Contract\ConfigInterface 内,换个方式理解也就是与 config/autoload/commands.php 对应
+ 'commands' => [],
+ // 与 commands 类似
+ 'listeners' => [
+ BootApplicationListener::class,
+ ],
+ // 合并到 config/autoload/dependencies.php 文件
+ 'dependencies' => [
+ RequestIdGeneratorInterface::class => RequestIdGenerator::class,
+ ],
+ 'publish' => [
+ [
+ 'id' => 'MineAdmin-HttpServer-Trans',
+ 'description' => 'MineAdmin Response Code Translation File',
+ 'source' => __DIR__ . '/../publish/languages/en/result.php',
+ 'destination' => BASE_PATH . '/storage/languages/en/result.php',
+ ],
+ [
+ 'id' => 'MineAdmin-HttpServer-Trans zh_CN',
+ 'description' => 'MineAdmin Response Code Translation File',
+ 'source' => __DIR__ . '/../publish/languages/zh_CN/result.php',
+ 'destination' => BASE_PATH . '/storage/languages/zh_CN/result.php',
+ ],
+ ],
+ ];
+ }
+}
diff --git a/src/HttpServer/src/Constant/HttpResultCode.php b/src/HttpServer/src/Constant/HttpResultCode.php
new file mode 100644
index 00000000..6914d53f
--- /dev/null
+++ b/src/HttpServer/src/Constant/HttpResultCode.php
@@ -0,0 +1,160 @@
+getTrans()) ? $message : $code->getTrans();
+ $code = $code->value;
+ }
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/src/HttpServer/src/Exception/Handler/HttpExceptionHandler.php b/src/HttpServer/src/Exception/Handler/HttpExceptionHandler.php
new file mode 100644
index 00000000..6b76c924
--- /dev/null
+++ b/src/HttpServer/src/Exception/Handler/HttpExceptionHandler.php
@@ -0,0 +1,45 @@
+getMessage(),
+ code: $throwable->getCode()
+ );
+ return $response
+ ->setBody(
+ new SwooleStream((string) $result)
+ );
+ }
+
+ public function isValid(\Throwable $throwable): bool
+ {
+ return $throwable instanceof HttpException;
+ }
+}
diff --git a/src/HttpServer/src/Exception/HttpException.php b/src/HttpServer/src/Exception/HttpException.php
new file mode 100644
index 00000000..049140ef
--- /dev/null
+++ b/src/HttpServer/src/Exception/HttpException.php
@@ -0,0 +1,15 @@
+merge(__FUNCTION__);
+ }
+
+ public function attributes(): array
+ {
+ return $this->merge(__FUNCTION__);
+ }
+
+ public function rules(): array
+ {
+ return $this->merge(__FUNCTION__);
+ }
+
+ private function merge(string $function): array
+ {
+ $commonFunc = 'common' . ucfirst($function);
+ $actionFunc = $this->getAction() . ucfirst($function);
+ return array_merge(
+ $this->{$commonFunc}(),
+ $this->{$actionFunc}()
+ );
+ }
+}
diff --git a/src/HttpServer/src/Listener/BootApplicationListener.php b/src/HttpServer/src/Listener/BootApplicationListener.php
new file mode 100644
index 00000000..29e25e6f
--- /dev/null
+++ b/src/HttpServer/src/Listener/BootApplicationListener.php
@@ -0,0 +1,84 @@
+registerRequestMacro();
+ $this->registerResponseMacro();
+ }
+
+ private function registerResponseMacro(): void
+ {
+ ApplicationContext::getContainer()->set(Response::class, MineResponse::class);
+ }
+
+ private function registerRequestMacro(): void
+ {
+ Request::macro('ip', function () {
+ /**
+ * @var Request $this
+ */
+ $ip = $this->getServerParams()['remote_addr'] ?? '0.0.0.0';
+ $headers = $this->getHeaders();
+ if (isset($headers['x-real-ip'])) {
+ $ip = $headers['x-real-ip'][0];
+ } elseif (isset($headers['x-forwarded-for'])) {
+ $ip = $headers['x-forwarded-for'][0];
+ } elseif (isset($headers['http_x_forwarded_for'])) {
+ $ip = $headers['http_x_forwarded_for'][0];
+ } elseif (isset($headers['remote_host'])) {
+ $ip = $headers['remote_host'][0];
+ }
+ return $ip;
+ });
+
+ Request::macro('getAction', function () {
+ /**
+ * @var Dispatched $dispatch
+ * @var Request $this
+ */
+ $dispatch = $this->getAttribute(Dispatched::class);
+ $callback = $dispatch?->handler?->callback;
+ if (is_array($callback) && count($callback) === 2) {
+ return $callback[1];
+ }
+ if (is_string($callback)) {
+ if (str_contains($callback, '@')) {
+ return explode('@', $callback)[1] ?? null;
+ }
+ if (str_contains($callback, '::')) {
+ return explode('::', $callback)[1] ?? null;
+ }
+ }
+ return null;
+ });
+ }
+}
diff --git a/src/HttpServer/src/Log/Processor/RequestIdProcessor.php b/src/HttpServer/src/Log/Processor/RequestIdProcessor.php
new file mode 100644
index 00000000..b85e18b7
--- /dev/null
+++ b/src/HttpServer/src/Log/Processor/RequestIdProcessor.php
@@ -0,0 +1,26 @@
+toString();
+ }
+ return (string) $this->container->get(IdGeneratorInterface::class)->generate();
+ });
+ }
+}
diff --git a/src/HttpServer/src/Middleware/CorsMiddleware.php b/src/HttpServer/src/Middleware/CorsMiddleware.php
new file mode 100644
index 00000000..b4fe28fe
--- /dev/null
+++ b/src/HttpServer/src/Middleware/CorsMiddleware.php
@@ -0,0 +1,36 @@
+withHeader('Access-Control-Allow-Origin', '*')
+ ->withHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
+ ->withHeader('Access-Control-Allow-Credentials', 'true')
+ ->withHeader('Access-Control-Allow-Headers', 'accept-language,authorization,lang,uid,token,Keep-Alive,User-Agent,Cache-Control,Content-Type');
+ Context::set(ResponseInterface::class, $response);
+ if ($request->getMethod() === 'OPTIONS') {
+ return $response;
+ }
+ return $handler->handle($request);
+ }
+}
diff --git a/src/HttpServer/src/Middleware/I18nMiddleware.php b/src/HttpServer/src/Middleware/I18nMiddleware.php
new file mode 100644
index 00000000..f42e9f56
--- /dev/null
+++ b/src/HttpServer/src/Middleware/I18nMiddleware.php
@@ -0,0 +1,61 @@
+hasHeader(self::HTTP_HEADER_KEY)) {
+ return $handler->handle($request);
+ }
+ $acceptLanguage = $request->getHeaderLine(self::HTTP_HEADER_KEY);
+ $locales = $this->getLocales();
+ if (! in_array($acceptLanguage, $locales, true)) {
+ return $handler->handle($request);
+ }
+ $this->translator->setLocale($acceptLanguage);
+ return $handler->handle($request);
+ }
+
+ private function getLocales(): array
+ {
+ $appLocales = $this->config->get('translatable.locales', []);
+ $locales = [];
+ foreach ($appLocales as $i => $v) {
+ if (is_int($i)) {
+ $locales[] = $v;
+ }
+ if (is_string($i) && is_array($v)) {
+ foreach ($v as $sub) {
+ $locales[] = $i . '_' . $sub;
+ }
+ }
+ }
+ return $locales;
+ }
+}
diff --git a/src/HttpServer/src/Middleware/JsonMiddleware.php b/src/HttpServer/src/Middleware/JsonMiddleware.php
new file mode 100644
index 00000000..48eeed39
--- /dev/null
+++ b/src/HttpServer/src/Middleware/JsonMiddleware.php
@@ -0,0 +1,26 @@
+handle($request)->withHeader('content-type', 'application/json; charset=utf-8');
+ }
+}
diff --git a/src/HttpServer/src/Middleware/RequestIdMiddleware.php b/src/HttpServer/src/Middleware/RequestIdMiddleware.php
new file mode 100644
index 00000000..2c2706bd
--- /dev/null
+++ b/src/HttpServer/src/Middleware/RequestIdMiddleware.php
@@ -0,0 +1,28 @@
+handle($request);
+ }
+}
diff --git a/src/HttpServer/src/RequestIdHolder.php b/src/HttpServer/src/RequestIdHolder.php
new file mode 100644
index 00000000..78989f7d
--- /dev/null
+++ b/src/HttpServer/src/RequestIdHolder.php
@@ -0,0 +1,25 @@
+get(RequestIdGeneratorInterface::class)->generate();
+ }
+}
diff --git a/src/HttpServer/src/Result.php b/src/HttpServer/src/Result.php
new file mode 100644
index 00000000..ac7108d8
--- /dev/null
+++ b/src/HttpServer/src/Result.php
@@ -0,0 +1,128 @@
+handleCode();
+ }
+
+ public function __toString(): string
+ {
+ return Json::encode($this->toArray());
+ }
+
+ public function isSuccess(): bool
+ {
+ return $this->success;
+ }
+
+ public function setSuccess(bool $success): void
+ {
+ $this->success = $success;
+ }
+
+ public function getMessage(): ?string
+ {
+ return $this->message;
+ }
+
+ public function setMessage(?string $message): void
+ {
+ $this->message = $message;
+ }
+
+ public function getCode(): null|HttpResultCode|int
+ {
+ return $this->code;
+ }
+
+ public function setCode(null|HttpResultCode|int $code): void
+ {
+ $this->code = $code;
+ $this->handleCode();
+ }
+
+ public function getData(): ?array
+ {
+ return $this->data;
+ }
+
+ public function setData(?array $data): void
+ {
+ $this->data = $data;
+ }
+
+ public function toArray(): array
+ {
+ $result = [
+ 'success' => $this->isSuccess(),
+ 'requestId' => RequestIdHolder::getId(),
+ ];
+ if ($this->getMessage()) {
+ $result['message'] = $this->getMessage();
+ }
+ if ($this->getData()) {
+ $result['data'] = $this->getData();
+ }
+ if ($this->getCode()) {
+ $result['code'] = $this->getCode();
+ }
+ return $result;
+ }
+
+ public static function success(
+ ?string $message = null,
+ array|object $data = [],
+ HttpResultCode|int $code = 200
+ ): self {
+ return new self(
+ success: true,
+ message: $message,
+ code: $code,
+ data: $data
+ );
+ }
+
+ public static function error(
+ ?string $message = null,
+ array|object $data = [],
+ HttpResultCode|int $code = 200
+ ): self {
+ return new self(
+ success: false,
+ message: $message,
+ code: $code,
+ data: $data
+ );
+ }
+
+ private function handleCode(): void
+ {
+ if ($this->getCode() instanceof HttpResultCode) {
+ $trans = $this->getCode()->getTrans();
+ $this->setMessage(empty($trans) ? $this->getMessage() : $trans);
+ $this->setCode($this->getCode()->value);
+ }
+ }
+}
diff --git a/src/HttpServer/src/Server.php b/src/HttpServer/src/Server.php
new file mode 100644
index 00000000..6f1f95ec
--- /dev/null
+++ b/src/HttpServer/src/Server.php
@@ -0,0 +1,17 @@
+assertIsArray((new ConfigProvider())());
+ }
+}
diff --git a/src/HttpServer/tests/Cases/Exception/BusinessExceptionTest.php b/src/HttpServer/tests/Cases/Exception/BusinessExceptionTest.php
new file mode 100644
index 00000000..59d830c0
--- /dev/null
+++ b/src/HttpServer/tests/Cases/Exception/BusinessExceptionTest.php
@@ -0,0 +1,70 @@
+ [
+ LogLevel::DEBUG,
+ ],
+ ]);
+ ApplicationContext::getContainer()
+ ->set(ConfigInterface::class, $config);
+ ApplicationContext::getContainer()->define(
+ RequestIdGeneratorInterface::class,
+ RequestIdGenerator::class
+ );
+ ApplicationContext::getContainer()
+ ->define(
+ RequestIdGeneratorInterface::class,
+ RequestIdGenerator::class
+ );
+ }
+
+ public function testConstruct(): void
+ {
+ $translator = \Mockery::mock(TranslatorInterface::class);
+ $translator->allows('trans')
+ ->withArgs(function ($key) {
+ return true;
+ })
+ ->andReturn('xxx');
+ ApplicationContext::getContainer()->set(TranslatorInterface::class, $translator);
+ $businessException = new BusinessException('xxx', 100);
+ $this->assertSame($businessException->getMessage(), 'xxx');
+ $this->assertSame($businessException->getCode(), 100);
+
+ $businessException = new BusinessException(code: HttpResultCode::SUCCESS);
+ $this->assertSame($businessException->getCode(), HttpResultCode::SUCCESS->value);
+ $this->assertSame($businessException->getMessage(), 'xxx');
+ }
+}
diff --git a/src/HttpServer/tests/Cases/Exception/Handler/HttpExceptionHandlerTest.php b/src/HttpServer/tests/Cases/Exception/Handler/HttpExceptionHandlerTest.php
new file mode 100644
index 00000000..8a259f5c
--- /dev/null
+++ b/src/HttpServer/tests/Cases/Exception/Handler/HttpExceptionHandlerTest.php
@@ -0,0 +1,72 @@
+define(
+ RequestIdGeneratorInterface::class,
+ RequestIdGenerator::class
+ );
+ }
+
+ public function testIsValid(): void
+ {
+ $reflection = new \ReflectionClass(HttpExceptionHandler::class);
+ $method = $reflection->getMethod('isValid');
+ $instance = \Mockery::mock(HttpExceptionHandler::class);
+ $this->assertTrue($method->invoke($instance, \Mockery::mock(HttpException::class)));
+ $this->assertFalse($method->invoke($instance, new \Exception()));
+ $this->assertTrue($method->invoke($instance, new class() extends HttpException {}));
+ }
+
+ public function testHandle(): void
+ {
+ $requestId = RequestIdHolder::getId();
+ $reflection = new \ReflectionClass(HttpExceptionHandler::class);
+ $method = $reflection->getMethod('handle');
+ $instance = \Mockery::mock(HttpExceptionHandler::class);
+ $response = \Mockery::mock(ResponsePlusInterface::class);
+ $response->allows('setBody')->withArgs(function (SwooleStream $stream) use ($requestId) {
+ $this->assertInstanceOf(SwooleStream::class, $stream);
+ $this->assertSame($stream->getContents(), '{"success":false,"requestId":"' . $requestId . '","message":"xxx","code":100}');
+ return true;
+ })->andReturn($response);
+ $method->invoke(
+ $instance,
+ new class() extends HttpException {
+ protected $message = 'xxx';
+
+ protected $code = 100;
+ },
+ $response
+ );
+ }
+}
diff --git a/src/HttpServer/tests/Cases/HttpRequestTest.php b/src/HttpServer/tests/Cases/HttpRequestTest.php
new file mode 100644
index 00000000..2c818ba8
--- /dev/null
+++ b/src/HttpServer/tests/Cases/HttpRequestTest.php
@@ -0,0 +1,114 @@
+process(new BootApplication());
+ parent::setUp(); // TODO: Change the autogenerated stub
+ }
+
+ public function testIp()
+ {
+ $request = new Request();
+ $interface = \Mockery::mock(ServerRequestPlusInterface::class);
+ $interface->allows('getHeaders')->andReturns(
+ [
+ 'x-real-ip' => ['127.0.0.1'],
+ 'x-forwarded-for' => ['127.0.0.2'],
+ ],
+ [
+ 'x-forwarded-for' => ['127.0.0.2'],
+ 'http_x_forwarded_for' => ['127.0.0.3'],
+ ],
+ [
+ 'http_x_forwarded_for' => ['127.0.0.3'],
+ 'remote_host' => ['127.0.0.4'],
+ ],
+ [
+ 'remote_host' => ['127.0.0.4'],
+ ],
+ );
+ $interface->allows('getServerParams')->andReturns([]);
+ RequestContext::set($interface);
+ self::assertSame($request->ip(), '127.0.0.1');
+ self::assertSame($request->ip(), '127.0.0.2');
+ self::assertSame($request->ip(), '127.0.0.3');
+ self::assertSame($request->ip(), '127.0.0.4');
+ }
+
+ public function testSchema()
+ {
+ $request = new Request();
+ $interface = \Mockery::mock(ServerRequestPlusInterface::class);
+ $interface->allows('getUri')->andReturns(
+ new Uri('https://baidu.com/?q=xxx'),
+ new Uri('http://baidu.com/?q=xxx'),
+ );
+ RequestContext::set($interface);
+ $this->assertSame($request->getUri()->getScheme(), 'https');
+ $this->assertSame($request->getUri()->getScheme(), 'http');
+ }
+
+ public function testGetAction()
+ {
+ $request = new Request();
+ $interface = \Mockery::mock(ServerRequestPlusInterface::class);
+ $dispatch = new Dispatched([
+ Dispatcher::FOUND,
+ new Handler([
+ 'error', 'index',
+ ], 'test'),
+ [],
+ ]);
+ $dispatch1 = new Dispatched([
+ Dispatcher::FOUND,
+ new Handler('index::index', 'test'),
+ [],
+ ]);
+
+ $dispatch2 = new Dispatched([
+ Dispatcher::FOUND,
+ new Handler('index@index', 'test'),
+ [],
+ ]);
+ $interface
+ ->allows('getAttribute')
+ ->andReturn(new Dispatched([
+ Dispatcher::NOT_FOUND,
+ ]), $dispatch, $dispatch1, $dispatch2);
+ RequestContext::set($interface);
+ $this->assertNull($request->getAction());
+ $this->assertSame($request->getAction(), 'index');
+ $this->assertSame($request->getAction(), 'index');
+ $this->assertSame($request->getAction(), 'index');
+ }
+}
diff --git a/src/HttpServer/tests/Cases/Log/Processor/RequestIdProcessorTest.php b/src/HttpServer/tests/Cases/Log/Processor/RequestIdProcessorTest.php
new file mode 100644
index 00000000..58dd0737
--- /dev/null
+++ b/src/HttpServer/tests/Cases/Log/Processor/RequestIdProcessorTest.php
@@ -0,0 +1,52 @@
+define(
+ RequestIdGeneratorInterface::class,
+ RequestIdGenerator::class
+ );
+ }
+
+ public function testInvoke(): void
+ {
+ $requestIdProcessor = new RequestIdProcessor();
+ $logRecord = new LogRecord(
+ \Mockery::mock(\DateTimeImmutable::class),
+ 'xxx',
+ Level::Alert,
+ 'xxx'
+ );
+ $requestIdProcessor($logRecord);
+ $this->assertArrayHasKey('request_id', $logRecord->extra);
+ $this->assertSame($logRecord->extra['request_id'], RequestIdHolder::getId());
+ }
+}
diff --git a/src/HttpServer/tests/Cases/Log/RequestIdGeneratorTest.php b/src/HttpServer/tests/Cases/Log/RequestIdGeneratorTest.php
new file mode 100644
index 00000000..b291f482
--- /dev/null
+++ b/src/HttpServer/tests/Cases/Log/RequestIdGeneratorTest.php
@@ -0,0 +1,40 @@
+get(RequestIdGenerator::class);
+ $id = $generator->generate();
+ self::assertIsString($id);
+ self::assertEquals($id, $generator->generate());
+ Coroutine::create(function () use ($id) {
+ $generator = ApplicationContext::getContainer()->get(RequestIdGenerator::class);
+ self::assertNotEquals($id, $generator->generate());
+ });
+ }
+}
diff --git a/src/HttpServer/tests/Cases/Middleware/CorsMiddlewareTest.php b/src/HttpServer/tests/Cases/Middleware/CorsMiddlewareTest.php
new file mode 100644
index 00000000..1a429616
--- /dev/null
+++ b/src/HttpServer/tests/Cases/Middleware/CorsMiddlewareTest.php
@@ -0,0 +1,56 @@
+allows('getMethod')->andReturn('GET', 'OPTIONS');
+ $handler = \Mockery::mock(RequestHandlerInterface::class);
+ $response = \Mockery::mock(ResponseInterface::class);
+ $handler->allows('handle')->andReturn($response);
+ $response->allows('withHeader')
+ ->andReturnUsing(function ($k, $v) use ($response) {
+ if ($k === 'Access-Control-Allow-Origin') {
+ $this->assertSame($v, '*');
+ }
+ if ($k === 'Access-Control-Allow-Methods') {
+ $this->assertSame($v, 'GET,PUT,POST,DELETE,OPTIONS');
+ }
+ if ($k === 'Access-Control-Allow-Credentials') {
+ $this->assertSame($v, 'true');
+ }
+ if ($k === 'Access-Control-Allow-Headers') {
+ $this->assertSame($v, 'accept-language,authorization,lang,uid,token,Keep-Alive,User-Agent,Cache-Control,Content-Type');
+ }
+ return $response;
+ });
+ Context::set(ResponseInterface::class, $response);
+ $corsMiddleware->process($request, $handler);
+ $corsMiddleware->process($request, $handler);
+ }
+}
diff --git a/src/HttpServer/tests/Cases/Middleware/I18nMiddlewareTest.php b/src/HttpServer/tests/Cases/Middleware/I18nMiddlewareTest.php
new file mode 100644
index 00000000..e74baa10
--- /dev/null
+++ b/src/HttpServer/tests/Cases/Middleware/I18nMiddlewareTest.php
@@ -0,0 +1,79 @@
+ [
+ LogLevel::DEBUG,
+ ],
+ 'translatable' => [
+ 'locales' => [
+ 'en',
+ 'zh' => [
+ 'CN',
+ 'TW',
+ ],
+ ],
+ ],
+ ]);
+ ApplicationContext::getContainer()
+ ->set(ConfigInterface::class, $config);
+ ApplicationContext::getContainer()->define(
+ RequestIdGeneratorInterface::class,
+ RequestIdGenerator::class
+ );
+ }
+
+ public function testProcess(): void
+ {
+ $instance = ApplicationContext::getContainer()->get(I18nMiddleware::class);
+ $request = \Mockery::mock(ServerRequestInterface::class);
+ $translator = ApplicationContext::getContainer()->get(TranslatorInterface::class);
+ $request->allows('hasHeader')
+ ->andReturn(false, true, true, true, true);
+ $request->allows('getHeaderLine')
+ ->andReturn('en', 'zh_CN', 'zh_TW', 'test');
+ $handler = \Mockery::mock(RequestHandlerInterface::class);
+ $handler->allows('handle')->andReturn(\Mockery::mock(ResponseInterface::class));
+ $instance->process($request, $handler);
+ $this->assertSame($translator->getLocale(), 'zh_CN');
+ $instance->process($request, $handler);
+ $this->assertSame($translator->getLocale(), 'en');
+ $instance->process($request, $handler);
+ $this->assertSame($translator->getLocale(), 'zh_CN');
+ $instance->process($request, $handler);
+ $this->assertSame($translator->getLocale(), 'zh_TW');
+ }
+}
diff --git a/src/HttpServer/tests/Cases/Middleware/JsonMiddlewareTest.php b/src/HttpServer/tests/Cases/Middleware/JsonMiddlewareTest.php
new file mode 100644
index 00000000..bce55b6a
--- /dev/null
+++ b/src/HttpServer/tests/Cases/Middleware/JsonMiddlewareTest.php
@@ -0,0 +1,44 @@
+allows('withHeader')
+ ->withArgs(function ($key, $value) {
+ $this->assertSame($key, 'content-type');
+ $this->assertSame($value, 'application/json; charset=utf-8');
+ return true;
+ })->andReturn($response);
+ $handler = \Mockery::mock(RequestHandlerInterface::class);
+ $handler->allows('handle')
+ ->andReturn($response);
+ $request = \Mockery::mock(ServerRequestInterface::class);
+ $middleware->process($request, $handler);
+ }
+}
diff --git a/src/HttpServer/tests/Cases/Middleware/RequestIdMiddlewareTest.php b/src/HttpServer/tests/Cases/Middleware/RequestIdMiddlewareTest.php
new file mode 100644
index 00000000..b6ff54e0
--- /dev/null
+++ b/src/HttpServer/tests/Cases/Middleware/RequestIdMiddlewareTest.php
@@ -0,0 +1,58 @@
+define(
+ RequestIdGeneratorInterface::class,
+ RequestIdGenerator::class
+ );
+ }
+
+ public function testProcess(): void
+ {
+ $middleware = new RequestIdMiddleware();
+ $response = \Mockery::mock(ResponsePlusInterface::class);
+ $response
+ ->allows('withHeader')
+ ->andReturn($response);
+ $handler = \Mockery::mock(RequestHandlerInterface::class);
+ $handler->allows('handle')
+ ->andReturn($response);
+ $request = \Mockery::mock(ServerRequestInterface::class);
+ $middleware->process($request, $handler);
+ $this->assertSame(
+ Context::get(RequestIdGeneratorInterface::REQUEST_ID),
+ RequestIdHolder::getId()
+ );
+ }
+}
diff --git a/src/HttpServer/tests/Cases/ResultTest.php b/src/HttpServer/tests/Cases/ResultTest.php
new file mode 100644
index 00000000..733eb399
--- /dev/null
+++ b/src/HttpServer/tests/Cases/ResultTest.php
@@ -0,0 +1,112 @@
+ [
+ LogLevel::DEBUG,
+ ],
+ ]);
+ ApplicationContext::getContainer()
+ ->set(ConfigInterface::class, $config);
+ ApplicationContext::getContainer()->define(
+ RequestIdGeneratorInterface::class,
+ RequestIdGenerator::class
+ );
+ }
+
+ public function testConstruct(): void
+ {
+ $result = new Result(
+ true,
+ 'xxx',
+ HttpResultCode::SUCCESS,
+ );
+ $this->assertInstanceOf(Result::class, $result);
+ $this->assertSame($result->message, 'xxx');
+ $this->assertSame($result->getMessage(), 'xxx');
+ $this->assertNull($result->getData());
+ $this->assertNull($result->data);
+ $this->assertSame($result->getCode(), HttpResultCode::SUCCESS->value);
+ $this->assertSame($result->code, HttpResultCode::SUCCESS->value);
+
+ $result->setMessage('xx2');
+ $this->assertSame($result->message, 'xx2');
+ $this->assertSame($result->getMessage(), 'xx2');
+
+ $result->setCode(HttpResultCode::FAILED);
+ $this->assertSame($result->getCode(), HttpResultCode::FAILED->value);
+ $this->assertSame($result->code, HttpResultCode::FAILED->value);
+
+ $result->setData(['xxx']);
+ $this->assertSame($result->getData(), ['xxx']);
+ $this->assertSame($result->data, ['xxx']);
+ $this->assertSame($result->toArray(), [
+ 'success' => true,
+ 'requestId' => RequestIdHolder::getId(),
+ 'message' => 'xx2',
+ 'data' => [
+ 'xxx',
+ ],
+ 'code' => HttpResultCode::FAILED->value,
+ ]);
+ }
+
+ public function testSuccess(): void
+ {
+ $result = Result::success(
+ 'xxx',
+ ['xxx'],
+ HttpResultCode::SUCCESS
+ );
+ $this->assertSame($result->getMessage(), 'xxx');
+ $this->assertSame($result->getData(), ['xxx']);
+ $this->assertTrue($result->isSuccess());
+ $this->assertSame($result->data, ['xxx']);
+ $this->assertSame($result->getCode(), HttpResultCode::SUCCESS->value);
+ }
+
+ public function testFailed(): void
+ {
+ $result = Result::error(
+ 'xxx',
+ ['xxx'],
+ HttpResultCode::FAILED
+ );
+ $this->assertSame($result->getMessage(), 'xxx');
+ $this->assertSame($result->getData(), ['xxx']);
+ $this->assertFalse($result->isSuccess());
+ $this->assertSame($result->data, ['xxx']);
+ $this->assertSame($result->getCode(), HttpResultCode::FAILED->value);
+ }
+}
diff --git a/src/next-core-x/tests/Feature/Channel/RedisChannelTest.php b/src/next-core-x/tests/Feature/Channel/RedisChannelTest.php
index 32d1e9a9..081c49e1 100644
--- a/src/next-core-x/tests/Feature/Channel/RedisChannelTest.php
+++ b/src/next-core-x/tests/Feature/Channel/RedisChannelTest.php
@@ -11,11 +11,14 @@
*/
use Hyperf\Config\Config;
use Hyperf\Context\ApplicationContext;
+use Hyperf\Contract\ConfigInterface;
use Hyperf\Redis\Redis;
use Mine\NextCoreX\Channel\RedisChannel;
use Mine\NextCoreX\Protocols\PhpSerialize;
use Mine\NextCoreX\ReadConfig;
+use function Hyperf\Support\env;
+
beforeEach(function () {
$configInterface = new Config([
'next-core-x' => [
@@ -24,8 +27,25 @@
],
],
'serialize' => PhpSerialize::class,
+ 'redis' => [
+ 'default' => [
+ 'host' => env('REDIS_HOST', '127.0.0.1'),
+ 'auth' => env('REDIS_AUTH', null),
+ 'port' => (int) env('REDIS_PORT', 6379),
+ 'db' => (int) env('REDIS_DB', 0),
+ 'pool' => [
+ 'min_connections' => 1,
+ 'max_connections' => 10,
+ 'connect_timeout' => 10.0,
+ 'wait_timeout' => 3.0,
+ 'heartbeat' => -1,
+ 'max_idle_time' => (float) env('REDIS_MAX_IDLE_TIME', 60),
+ ],
+ ],
+ ],
]);
$this->config = new ReadConfig($configInterface);
+ ApplicationContext::getContainer()->set(ConfigInterface::class, $configInterface);
$redis = ApplicationContext::getContainer()->get(Redis::class);
$this->channel = new RedisChannel($this->config, $redis);
});
diff --git a/tests/Pest.php b/tests/Pest.php
index 175a4173..e3e27647 100644
--- a/tests/Pest.php
+++ b/tests/Pest.php
@@ -11,14 +11,20 @@
*/
use Hyperf\Context\ApplicationContext;
use Hyperf\Contract\ConfigInterface;
+use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Testing\Concerns\RunTestsInCoroutine;
use Mine\Tests\TestCase;
+use Psr\Log\LogLevel;
uses(TestCase::class)
->beforeEach(function () {
$mockConfig = Mockery::mock(ConfigInterface::class);
$mockConfig->allows('has')->andReturn(true);
- $mockConfig->allows('get')->andReturn([]);
+ $mockConfig->allows('get')->andReturn([
+ StdoutLoggerInterface::class => [
+ LogLevel::DEBUG,
+ ],
+ ]);
$mockConfig->allows('set')->andReturn(true);
ApplicationContext::getContainer()
->set(ConfigInterface::class, $mockConfig);