Files
code-center/src/modules/n5/index.ts

80 lines
2.6 KiB
TypeScript

import { User } from '@/models/user.ts';
import { omit } from 'es-toolkit';
import { IncomingMessage, ServerResponse } from 'http';
import { renderServerHtml } from '../html/render-server-html.ts';
import { baseURL } from '../domain.ts';
import { app } from '@/app.ts'
import { N5Service } from '@/routes/n5-link/modules/n5.services.ts';
type ProxyOptions = {
createNotFoundPage: (msg?: string) => any;
};
// /n5/:slug/
export const N5Proxy = async (req: IncomingMessage, res: ServerResponse, opts?: ProxyOptions) => {
const { url } = req;
const _url = new URL(url || '', baseURL);
const { pathname, searchParams } = _url;
let [user, app, userAppKey] = pathname.split('/').slice(1);
if (!app) {
opts?.createNotFoundPage?.('应用未找到');
return false;
}
let n5Data = null;
let data = null;
let link = '';
try {
const convexResult = await N5Service.getBySlug(app);
if (!convexResult || convexResult.length === 0) {
opts?.createNotFoundPage?.('应用未找到');
return false;
}
n5Data = convexResult[0];
data = n5Data.data ?? {};
link = data.link;
if (!link) {
opts?.createNotFoundPage?.('不存在对应的跳转的链接');
return false;
}
} catch (e) {
console.error('Error fetching N5 data:', e);
opts?.createNotFoundPage?.('应用数据异常');
return false;
}
if (data?.useOwnerToken) {
const userId = n5Data.userId;
if (!userId) {
opts?.createNotFoundPage?.('未绑定账号');
return false;
}
try {
const user = await User.findByPk(userId);
const token = await User.createJwksTokenResponse({ id: userId, username: user?.username || '' }, { hasRefreshToken: true });
const urlObj = new URL(link);
urlObj.searchParams.set('token', token.accessToken);
const resultLink = await fetch(urlObj.toString(), { method: 'GET' }).then(res => res.json())
res.end(JSON.stringify(resultLink));
} catch (e) {
console.error('Error fetching the link:', e);
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: '请求服务区失败' }));
}
return true;
}
const type = data?.type;
if (type === 'html-render') {
const createJson = omit(data, ['useOwnerToken', 'permission']);
const html = await fetch(link, { method: 'GET' }).then(res => res.text());
const renderedHtml = await renderServerHtml({
data: createJson,
pathname: _url.toString(),
}, html);
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(renderedHtml);
} else {
res.writeHead(302, {
Location: link,
});
}
res.end();
};