add router
This commit is contained in:
		@@ -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;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user