From ac90b2460747dcbb4abaea81f0a8beb136fbb2cd Mon Sep 17 00:00:00 2001 From: whyour Date: Sun, 10 Mar 2024 19:16:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20update=20=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 1 + .umirc.ts | 5 ++ back/config/index.ts | 1 + back/loaders/update.ts | 93 +++++++++++++++++++++++++++++++ back/update.ts | 24 ++++++++ docker/front.conf | 16 ++++++ ecosystem.config.js | 9 +++ package.json | 2 + src/pages/setting/checkUpdate.tsx | 4 +- src/pages/setting/other.tsx | 2 +- 10 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 back/loaders/update.ts create mode 100644 back/update.ts diff --git a/.env.example b/.env.example index 2fc5d929..4f693d43 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ +UPDATE_PORT=5300 PUBLIC_PORT=5400 CRON_PORT=5500 BACK_PORT=5600 diff --git a/.umirc.ts b/.umirc.ts index cd7ebbc0..9305d573 100644 --- a/.umirc.ts +++ b/.umirc.ts @@ -16,6 +16,11 @@ export default defineConfig({ favicons: [`https://qn.whyour.cn/favicon.svg`], publicPath: process.env.NODE_ENV === 'production' ? './' : '/', proxy: { + [`${baseUrl}api/update`]: { + target: 'http://127.0.0.1:5300/', + changeOrigin: true, + pathRewrite: { [`^${baseUrl}api/update`]: '/api' }, + }, [`${baseUrl}api/public`]: { target: 'http://127.0.0.1:5400/', changeOrigin: true, diff --git a/back/config/index.ts b/back/config/index.ts index 35f3bfa9..437b9856 100644 --- a/back/config/index.ts +++ b/back/config/index.ts @@ -57,6 +57,7 @@ export default { port: parseInt(process.env.BACK_PORT as string, 10), cronPort: parseInt(process.env.CRON_PORT as string, 10), publicPort: parseInt(process.env.PUBLIC_PORT as string, 10), + updatePort: parseInt(process.env.UPDATE_PORT as string, 10), secret: process.env.SECRET || createRandomString(16, 32), logs: { level: process.env.LOG_LEVEL || 'silly', diff --git a/back/loaders/update.ts b/back/loaders/update.ts new file mode 100644 index 00000000..7dbc995a --- /dev/null +++ b/back/loaders/update.ts @@ -0,0 +1,93 @@ +import bodyParser from 'body-parser'; +import { errors } from 'celebrate'; +import cors from 'cors'; +import { Application, NextFunction, Request, Response } from 'express'; +import jwt from 'express-jwt'; +import Container from 'typedi'; +import { Logger } from 'winston'; +import config from '../config'; +import SystemService from '../services/system'; + +export default ({ app }: { app: Application }) => { + app.set('trust proxy', 'loopback'); + app.use(cors()); + + app.use(bodyParser.json({ limit: '50mb' })); + app.use(bodyParser.urlencoded({ limit: '50mb', extended: true })); + + app.use( + jwt({ + secret: config.secret, + algorithms: ['HS384'], + }), + ); + + app.put( + '/api/system', + async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + const systemService = Container.get(SystemService); + const result = await systemService.reloadSystem('system'); + res.send(result); + } catch (e) { + logger.error('🔥 error: %o', e); + return next(e); + } + }, + ); + app.put( + '/api/data', + async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + const systemService = Container.get(SystemService); + const result = await systemService.reloadSystem('data'); + res.send(result); + } catch (e) { + logger.error('🔥 error: %o', e); + return next(e); + } + }, + ); + + app.use((req, res, next) => { + const err: any = new Error('Not Found'); + err['status'] = 404; + next(err); + }); + + app.use(errors()); + + app.use( + ( + err: Error & { status: number }, + req: Request, + res: Response, + next: NextFunction, + ) => { + if (err.name === 'UnauthorizedError') { + return res + .status(err.status) + .send({ code: 401, message: err.message }) + .end(); + } + return next(err); + }, + ); + + app.use( + ( + err: Error & { status: number }, + req: Request, + res: Response, + next: NextFunction, + ) => { + res.status(err.status || 500); + res.json({ + code: err.status || 500, + message: err.message, + }); + }, + ); +}; diff --git a/back/update.ts b/back/update.ts new file mode 100644 index 00000000..de2de66c --- /dev/null +++ b/back/update.ts @@ -0,0 +1,24 @@ +import 'reflect-metadata'; // We need this in order to use @Decorators +import config from './config'; +import express from 'express'; +import Logger from './loaders/logger'; + +async function startServer() { + const app = express(); + + await require('./loaders/update').default({ app }); + + app + .listen(config.updatePort, () => { + Logger.debug(`✌️ 更新服务启动成功!`); + console.debug(`✌️ 更新服务启动成功!`); + process.send?.('ready'); + }) + .on('error', (err) => { + Logger.error(err); + console.error(err); + process.exit(1); + }); +} + +startServer(); diff --git a/docker/front.conf b/docker/front.conf index 3253be1c..ee2cb9d7 100644 --- a/docker/front.conf +++ b/docker/front.conf @@ -6,6 +6,10 @@ upstream publicApi { server 0.0.0.0:5400; } +upstream updateApi { + server 0.0.0.0:5300; +} + map $http_upgrade $connection_upgrade { default keep-alive; 'websocket' upgrade; @@ -16,6 +20,18 @@ server { IPV6_CONFIG ssl_session_timeout 5m; + location QL_BASE_URLapi/update/ { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://updateApi/api/; + proxy_buffering off; + proxy_redirect default; + proxy_connect_timeout 1800; + proxy_send_timeout 1800; + proxy_read_timeout 1800; + } + location QL_BASE_URLapi/public/ { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; diff --git a/ecosystem.config.js b/ecosystem.config.js index 0a48440c..0bf356ca 100644 --- a/ecosystem.config.js +++ b/ecosystem.config.js @@ -1,5 +1,14 @@ module.exports = { apps: [ + { + name: 'update', + max_restarts: 10, + kill_timeout: 15000, + wait_ready: true, + listen_timeout: 10000, + time: true, + script: 'static/build/update.js', + }, { name: 'schedule', max_restarts: 10, diff --git a/package.json b/package.json index 45ae341c..dcbc4453 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "start": "concurrently -n w: npm:start:*", "start:front": "max dev", "start:back": "nodemon", + "start:update": "ts-node -P tsconfig.back.json ./back/update.ts", "start:public": "ts-node -P tsconfig.back.json ./back/public.ts", "start:rpc": "ts-node -P tsconfig.back.json ./back/schedule/index.ts", "build:front": "max build", @@ -11,6 +12,7 @@ "panel": "npm run build:back && node static/build/app.js", "schedule": "npm run build:back && node static/build/schedule/index.js", "public": "npm run build:back && node static/build/public.js", + "update": "npm run build:back && node static/build/update.js", "gen:proto": "protoc --experimental_allow_proto3_optional --plugin=./node_modules/.bin/protoc-gen-ts_proto ./back/protos/*.proto --ts_proto_out=./ --ts_proto_opt=outputServices=grpc-js,env=node,esModuleInterop=true", "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'", "postinstall": "max setup 2>/dev/null || true", diff --git a/src/pages/setting/checkUpdate.tsx b/src/pages/setting/checkUpdate.tsx index f42bc849..ea82a030 100644 --- a/src/pages/setting/checkUpdate.tsx +++ b/src/pages/setting/checkUpdate.tsx @@ -116,7 +116,7 @@ const CheckUpdate = ({ systemInfo }: any) => { const reloadSystem = (type?: string) => { request - .put(`${config.apiPrefix}system/reload`, { type }) + .put(`${config.apiPrefix}update/${type}`) .then((_data: any) => { message.success({ content: ( @@ -220,7 +220,7 @@ const CheckUpdate = ({ systemInfo }: any) => {