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(); };