From 175e685480a3eb59a96e57160b9d06a5820c401c Mon Sep 17 00:00:00 2001 From: xion Date: Tue, 15 Oct 2024 18:53:09 +0800 Subject: [PATCH] add router --- package.json | 1 - src/module/get-user-app.ts | 53 ++++++++-------------------- src/module/index.ts | 6 +--- src/module/proxy.ts | 64 ---------------------------------- src/module/query/get-router.ts | 27 ++++++++++++-- src/route/app/list.ts | 29 +++++++++++++-- 6 files changed, 67 insertions(+), 113 deletions(-) delete mode 100644 src/module/proxy.ts diff --git a/package.json b/package.json index 4865f44..699f748 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "@abearxiong/router": "0.0.1-alpha.43", "@abearxiong/use-config": "^0.0.2", "@abearxiong/use-file-store": "^0.0.1", - "http-proxy": "^1.18.1", "ioredis": "^5.4.1", "nanoid": "^5.0.7" }, diff --git a/src/module/get-user-app.ts b/src/module/get-user-app.ts index e958ea9..4e40130 100644 --- a/src/module/get-user-app.ts +++ b/src/module/get-user-app.ts @@ -7,6 +7,7 @@ import crypto from 'crypto'; import { nanoid } from 'nanoid'; import { pipeline } from 'stream'; import { promisify } from 'util'; +import { fetchApp, fetchDomain, fetchTest } from './query/get-router.ts'; const pipelineAsync = promisify(pipeline); const { resources, api } = useConfig<{ resources: string; api: { host: string; path: string } }>(); @@ -44,9 +45,13 @@ type UserAppOptions = { export class UserApp { user: string; app: string; + isTest: boolean; constructor(options: UserAppOptions) { this.user = options.user; this.app = options.app; + if (this.user === 'test') { + this.isTest = true; + } } async getExist() { const app = this.app; @@ -63,6 +68,7 @@ export class UserApp { if (!value) { return null; } + return JSON.parse(value); } async getFile(appFileUrl: string) { const app = this.app; @@ -83,29 +89,12 @@ export class UserApp { } // 获取域名对应的用户和应用 - const fetchUrl = 'http://' + api.host + api.path; - const fetchRes = await fetch(fetchUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - path: 'app', - key: 'getDomainApp', - data: { - domain, - }, - }), - }) - .then((res) => { - return res.json(); - }) - .catch((err) => { - return { - code: 500, - message: err, - }; - }); + const fetchRes = await fetchDomain(domain).catch((err) => { + return { + code: 500, + message: err, + }; + }); if (fetchRes?.code !== 200) { console.log('fetchRes is error', fetchRes); return null; @@ -139,28 +128,16 @@ export class UserApp { async setCacheData() { const app = this.app; const user = this.user; + const isTest = this.isTest; const key = 'user:app:' + app + ':' + user; - const fetchUrl = 'http://' + api.host + api.path; if (status[key]) { return { loading: true, }; } status[key] = true; - const fetchRes = await fetch(fetchUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - path: 'app', - key: 'getApp', - data: { - user, - key: app, - }, - }), - }).then((res) => res.json()); + + const fetchRes = isTest ? await fetchTest(app) : await fetchApp({ user, app }); if (fetchRes?.code !== 200) { console.log('fetchRes is error', fetchRes); this.setLoaded(); diff --git a/src/module/index.ts b/src/module/index.ts index 72602d1..9e9c880 100644 --- a/src/module/index.ts +++ b/src/module/index.ts @@ -8,7 +8,6 @@ import { useConfig } from '@abearxiong/use-config'; import { redis } from './redis/redis.ts'; import { getContentType } from './get-content-type.ts'; import { sleep } from '@/utils/sleep.ts'; -import { handleProxyRequest } from './proxy.ts'; const { api, domain, allowedOrigins } = useConfig<{ api: { host: string; @@ -71,10 +70,7 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR res.end('not catch api'); return; } - if (req.url.startsWith('/test')) { - handleProxyRequest(req, res); - return; - } + const dns = getDNS(req); // 配置可以跨域 // 配置可以访问的域名 localhost, xiongxiao.me diff --git a/src/module/proxy.ts b/src/module/proxy.ts deleted file mode 100644 index e987ced..0000000 --- a/src/module/proxy.ts +++ /dev/null @@ -1,64 +0,0 @@ -import http from 'http'; -import httpProxy from 'http-proxy'; -import { useConfig } from '@abearxiong/use-config'; - -const { resources, api } = useConfig<{ - resources: string; - api: { host: string }; -}>(); -const proxy = httpProxy.createProxyServer({}); -const fetchTest = async (id: string) => { - const fetchUrl = 'http://' + api.host + '/api/router'; - const fetchRes = await fetch(fetchUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - path: 'user-app', - key: 'test', - id: id, - }), - }).then((res) => res.json()); - return fetchRes; -}; -// 60939f5e-f51b-4563-8c96-7a98ac5ac259 -export const handleProxyRequest = async (req: http.IncomingMessage, res: http.ServerResponse) => { - const url = req.url; - const urls = url.split('/'); - const [_, test, id] = urls; - const error = (msg: string) => { - res.writeHead(404, { 'Content-Type': 'text/plain' }); - res.write(msg); - res.end(); - }; - if (test !== 'test') { - error('Not Found'); - return; - } - if (!id) { - error('Need Test ID'); - return; - } - // 判断id是uuid - if (!isUUID(id)) { - error('Need Test ID is UUID'); - return; - } - const result = await fetchTest(id); - console.log('data', result); - if (result.code !== 200) { - error('fetch error'); - return; - } - const files = result.data?.data?.files; - const appFileUrl = (url + '').replace(`/${test}/${id}/`, ''); - const pathFile = files.find((file: any) => file.name === appFileUrl); - const target = `https://${resources}/${pathFile.path}`; - console.log('target', target); - proxy.web(req, res, { target: target, secure: false }); -}; -function isUUID(id: string): boolean { - const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; - return uuidRegex.test(id); -} diff --git a/src/module/query/get-router.ts b/src/module/query/get-router.ts index 30e2809..6a09735 100644 --- a/src/module/query/get-router.ts +++ b/src/module/query/get-router.ts @@ -2,11 +2,13 @@ import { useConfig } from '@abearxiong/use-config'; const { resources, api } = useConfig<{ resources: string; - api: { host: string }; + api: { host: string; path: string }; + ƒ; }>(); +const apiPath = api.path || '/api/router'; export const fetchTest = async (id: string) => { - const fetchUrl = 'http://' + api.host + '/api/router'; + const fetchUrl = 'http://' + api.host + apiPath; const fetchRes = await fetch(fetchUrl, { method: 'POST', headers: { @@ -22,7 +24,7 @@ export const fetchTest = async (id: string) => { }; export const fetchDomain = async (domain: string) => { - const fetchUrl = 'http://' + api.host + '/api/router'; + const fetchUrl = 'http://' + api.host + apiPath; const fetchRes = await fetch(fetchUrl, { method: 'POST', headers: { @@ -38,3 +40,22 @@ export const fetchDomain = async (domain: string) => { }).then((res) => res.json()); return fetchRes; }; + +export const fetchApp = async ({ user, app }) => { + const fetchUrl = 'http://' + api.host + apiPath; + const fetchRes = await fetch(fetchUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + path: 'app', + key: 'getApp', + data: { + user, + key: app, + }, + }), + }).then((res) => res.json()); + return fetchRes; +}; diff --git a/src/route/app/list.ts b/src/route/app/list.ts index 1d76531..83dbab3 100644 --- a/src/route/app/list.ts +++ b/src/route/app/list.ts @@ -59,7 +59,7 @@ app app .route({ path: 'app', - key: 'deleteAllForce', + key: 'clear', }) .define(async (ctx) => { const keys = await redis.keys('user:app:*'); @@ -69,4 +69,29 @@ app ctx.body = { keys, }; - }); + }) + .addTo(app); + +app + .route({ + path: 'app', + key: 'get', + }) + .define(async (ctx) => { + const { user, app } = ctx.query.data || {}; + if (!user || !app) { + if (!user) { + throw new CustomError('user is required'); + } + if (!app) { + throw new CustomError('app is required'); + } + } + const userApp = new UserApp({ user, app }); + const cache = await userApp.getCache(); + if (!cache) { + throw new CustomError('Not Found App'); + } + ctx.body = cache; + }) + .addTo(app);