add router
This commit is contained in:
parent
6b5eec89ed
commit
175e685480
@ -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"
|
||||
},
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user