Skip to content

Commit

Permalink
feat: add new CN site with alias "cnn", add redirect server
Browse files Browse the repository at this point in the history
  • Loading branch information
dreamerblue committed Jun 29, 2023
1 parent 2ea764c commit 5802e24
Show file tree
Hide file tree
Showing 14 changed files with 717 additions and 480 deletions.
34 changes: 32 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ jobs:
- uses: pnpm/[email protected]
with:
version: 6.0.2
- run: pnpm run ci
- run: SITE_ALIAS=cn pnpm run build
- run: pnpm run ci:server
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
Expand All @@ -62,3 +61,34 @@ jobs:
file: ./Dockerfile-CN
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/rankland-fe:cn
build-and-push-for-cnn:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- uses: pnpm/[email protected]
with:
version: 6.0.2
- run: pnpm run ci
- run: SITE_ALIAS=cnn pnpm run build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
version: v0.9.1
driver-opts: |
image=moby/buildkit:v0.10.6
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Image for CN Next Site
uses: docker/[email protected]
with:
context: ./
file: ./Dockerfile-CN-Next
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/rankland-fe:cnn
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ node_modules
/dist
/logs
/分发
.pnpm-debug.log
npm-debug.log*
6 changes: 3 additions & 3 deletions .umirc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const isProd = process.env.NODE_ENV === 'production';
const siteAlias = process.env.SITE_ALIAS;

const outputPath = isProd && siteAlias === 'cn' ? '分发' : 'dist';
const publicProdPrefix = siteAlias === 'cn' ? 'https://内容分发网络.算法与用户体验.中国/榜单大陆/' : '/';
const publicProdPrefix = siteAlias === 'cn' ? 'https://内容分发网络.算法与用户体验.中国/榜单大陆/' : siteAlias === 'cnn' ? 'https://内容分发网络.算法与用户体验.中国/rl/' : '/';
const publicPath = isProd ? `${publicProdPrefix}${outputPath}/` : `http://127.0.0.1:8000/${outputPath}/`;
console.log(
'Build options:',
Expand Down Expand Up @@ -42,8 +42,8 @@ export default defineConfig({
'process.env.WS_BASE': isProd ? 'wss://rl.mushan.top' : 'ws://rl_dev.mushan.top',
'process.env.SITE_ALIAS': process.env.SITE_ALIAS,
'process.env.HOST_GLOBAL': 'rl.algoux.org',
'process.env.HOST_CN': '榜单大陆.算法与用户体验.中国',
'process.env.BEIAN': '粤ICP备2022146651号',
'process.env.HOST_CN': 'rl.algoux.cn',
'process.env.BEIAN': '鲁ICP备18021776号-5',
'process.env.LIVE_POLLING_INTERVAL': '10000',
'process.env.X_PHOTO_BASE': 'https://share-bj-1252277595.cos.ap-beijing.myqcloud.com/',
'GTAG': siteAlias === 'cn' ? 'G-D4PSNCRQJC' : 'G-D6CVTJBDZT',
Expand Down
11 changes: 11 additions & 0 deletions Dockerfile-CN-Next
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM algoux/nodebase:16

WORKDIR /app/

COPY package.json ./
COPY server ./server
COPY dist ./dist

ENV PATH="/app/server/node_modules/pm2/bin:${PATH}"
ENV SITE_ALIAS=cnn
CMD npm run start:docker
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
"ci:server": "cd server && pnpm i --frozen-lockfile && cd ..",
"dev:client": "cross-env NODE_ENV=development umi dev",
"dev:server": "cross-env NODE_ENV=development nodemon --inspect=127.0.0.1:9239 --delay 0.2 server/index.js",
"dev:server:redirect": "cross-env NODE_ENV=development nodemon --inspect=127.0.0.1:9239 --delay 0.2 server/deprecated-redirect.js",
"dev": "concurrently \"npm:dev:client\" \"npm:dev:server\"",
"build": "umi build",
"start": "NODE_ENV=production node server/index.js",
"postinstall": "umi generate tmp",
"theme:antd": "lessc --js src/styles/antd.light.less src/styles/antd.light.css && lessc --js src/styles/antd.dark.less src/styles/antd.dark.css",
"build:type-checker": "`npm bin`/ts-interface-builder -o src/lib/srk-checker -s .ti node_modules/@algoux/standard-ranklist/index.d.ts",
"start:docker": "cd server && npm start && cd .."
"start:docker": "cd server && npm start && cd ..",
"start:docker:redirect": "cd server && npm run start:redirect && cd .."
},
"dependencies": {
"@algoux/standard-ranklist-renderer-component": "^0.3.14",
Expand Down
122 changes: 122 additions & 0 deletions server/deprecated-redirect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/* eslint-disable @typescript-eslint/no-require-imports */
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');
const winston = require('winston');
const dayjs = require('dayjs');
const { v4: uuidv4 } = require('uuid');

const port = parseInt(process.env.PORT, 10) || 7002;

const NEW_HOST = 'https://rl.algoux.cn';

const knownUrlKeywordToGeneralReplacementMap = {
当前选中榜单的标识符: 'rankId',
由官方整理和维护的: 'official',
榜单合集: 'collection',
探索: 'search',
榜单: 'ranklist',
游乐场: 'playground',
直播: 'live',
关键词: 'kw',
聚焦: 'focus',
: 'yes',
};

const convertUrl = (url) => {
let newUrl = url;
Object.keys(knownUrlKeywordToGeneralReplacementMap).forEach((key) => {
newUrl = newUrl.replace(key, knownUrlKeywordToGeneralReplacementMap[key]);
});
return newUrl;
};

// app logger
const appLoggingFormat = winston.format.printf(({ level, message, timestamp }) => {
return `${dayjs(timestamp).format('YYYY-MM-DDTHH:mm:ssZ')} [${level}] ${message}`;
});
const appLogger = winston.createLogger({
level: 'info',
format: winston.format.combine(winston.format.splat(), winston.format.timestamp(), appLoggingFormat),
transports: [
new winston.transports.File({ filename: 'logs/app-redirect-error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/app-redirect-all.log' }),
new winston.transports.Console(),
],
});

// koa app
const app = new Koa();
app.proxy = true;

// request id middleware
app.use(async (ctx, next) => {
ctx.requestId = uuidv4().substr(0, 8);
ctx.set('X-Request-Id', ctx.requestId);
return next();
});

// time cost middleware
app.use(async (ctx, next) => {
const _s = Date.now();
ctx.startAt = _s;
await next();
ctx.set('X-Response-Time', Date.now() - _s);
});

// error handler middleware
app.use(async (ctx, next) => {
try {
await next();
} catch (e) {
ctx.logger.error('Uncaught error: %O', e);
ctx.throw(500, 'Internal Server Error');
}
});

app.use(bodyParser());

// ctx logger middleware
app.use((ctx, next) => {
if (!ctx.logger) {
const ctxLoggingFormat = winston.format.printf(({ level, message, timestamp }) => {
return `${dayjs(timestamp).format('YYYY-MM-DDTHH:mm:ssZ')} [${level}] [${process.pid}] [${ctx.requestId}] [${
ctx.ip
}/${Date.now() - ctx.startAt}ms ${ctx.method.toUpperCase()} ${ctx.url}] ${message}`;
});
ctx.logger = winston.createLogger({
level: 'info',
format: winston.format.combine(winston.format.splat(), winston.format.timestamp(), ctxLoggingFormat),
transports: [
new winston.transports.File({ filename: 'logs/ctx-redirect-error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/ctx-redirect-all.log' }),
new winston.transports.Console(),
],
});
}
return next();
});

const router = new Router();

router.get('*', (ctx, next) => {
const newQuery = {};
Object.keys(ctx.query).forEach((key) => {
const k = knownUrlKeywordToGeneralReplacementMap[key] || key;
newQuery[k] = ctx.query[key];
});
const search = new URLSearchParams(newQuery).toString();
const newUrl = `${convertUrl(decodeURIComponent(ctx.path))}${search ? `?${search}` : ''}`;
const nextUrl = `${NEW_HOST}${newUrl}`;
ctx.logger.info('Redirecting to %s', nextUrl);
ctx.redirect(nextUrl);
});

app.use(router.routes()).use(router.allowedMethods());

async function main() {
app.listen(port);
console.log(`Redirection Server is listening on http://localhost:${port} (pid: ${process.pid})`);
}

main();
4 changes: 3 additions & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
"private": true,
"author": "bLue",
"scripts": {
"start": "NODE_ENV=production pm2-runtime pm2.config.js"
"start": "NODE_ENV=production pm2-runtime pm2.config.js",
"start:redirect": "NODE_ENV=production pm2-runtime pm2-redirect.config.js"
},
"dependencies": {
"dayjs": "^1.11.5",
"koa": "^2.13.4",
"koa-bodyparser": "^4.3.0",
"koa-compress": "^5.1.0",
"koa-mount": "^4.0.0",
"koa-router": "^7.4.0",
"koa-static": "^5.0.0",
"koa2-proxy-middleware": "^0.0.4",
"pm2": "^5.2.0",
Expand Down
20 changes: 20 additions & 0 deletions server/pm2-redirect.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
apps: [
{
name: 'rankland-fe',
cwd: '../',
script: `server/deprecated-redirect.js`,
max_memory_restart: '500M',
exec_mode: 'cluster',
instances: parseInt(process.env.WORKERS, 10) || 1,
out_file: `logs/pm2-out.log`,
error_file: `logs/pm2-error.log`,
log_date_format: 'YYYY-MM-DD HH:mm:ss',
merge_logs: true,
min_uptime: '5s',
env: {
NODE_ENV: 'production',
},
},
],
};
Loading

0 comments on commit 5802e24

Please sign in to comment.