mirror of
https://github.com/2234839/web-font.git
synced 2025-05-13 06:59:02 +08:00
119 lines
4.3 KiB
TypeScript
119 lines
4.3 KiB
TypeScript
import fs, { readFile } from "fs/promises";
|
||
import * as path from "path";
|
||
import { fontSubset } from "./font_util/font";
|
||
import { mimeTypes } from "./server/mime_type";
|
||
import type { cMiddleware } from "./server/req_res";
|
||
import { SimpleHttpServer } from "./server/server";
|
||
const ROOT_DIR = path.resolve("dist"); // 静态文件目录
|
||
const staticFileMiddleware: cMiddleware = async function (req, res, next) {
|
||
if (req.method === "GET") {
|
||
const filePath = path.join(ROOT_DIR, req.url === "/" ? "index.html" : req.url);
|
||
|
||
try {
|
||
const stats = await fs.stat(filePath);
|
||
|
||
if (stats.isFile()) {
|
||
const fileContent = await fs.readFile(filePath);
|
||
const extname = path.extname(filePath);
|
||
res.statusCode = 200;
|
||
res.headers["Content-Type"] = mimeTypes[extname] || "application/octet-stream";
|
||
res.headers["Content-Length"] = `${stats.size}`;
|
||
res.body = fileContent;
|
||
} else {
|
||
// 文件不存在
|
||
res.statusCode = 404;
|
||
res.headers["Content-Type"] = "text/plain";
|
||
res.body = "404 Not Found";
|
||
}
|
||
} catch (err) {
|
||
// 错误处理
|
||
res.statusCode = 404;
|
||
res.headers["Content-Type"] = "text/plain";
|
||
res.body = `404 Not Found`;
|
||
}
|
||
} else {
|
||
// 返回 405 Method Not Allowed
|
||
res.statusCode = 405;
|
||
res.headers["Content-Type"] = "text/plain";
|
||
res.body = "Method Not Allowed";
|
||
}
|
||
return next(req, res);
|
||
};
|
||
const logMiddleware: cMiddleware = async (req, res, next) => {
|
||
const t1 = Date.now();
|
||
const r = await next(req, res);
|
||
const t2 = Date.now();
|
||
console.log(`[${t2 - t1}ms] ${req.url}`);
|
||
return r;
|
||
};
|
||
const corsMiddleware: cMiddleware = async (req, res, next) => {
|
||
// 允许所有域跨域请求
|
||
res.headers["Access-Control-Allow-Origin"] = "*";
|
||
// 如果你只想允许特定域名:
|
||
// res.headers["Access-Control-Allow-Origin"] = "https://example.com";
|
||
// 允许常见的 HTTP 方法
|
||
res.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS";
|
||
// 允许的请求头
|
||
res.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization";
|
||
|
||
// 如果是 OPTIONS 请求(预检请求),直接返回成功响应
|
||
if (req.method === "OPTIONS") {
|
||
res.statusCode = 204;
|
||
res.headers["Content-Length"] = "0";
|
||
res.body = "";
|
||
// 直接结束请求,不继续传递到下一个中间件
|
||
return { req, res };
|
||
} else {
|
||
return next(req, res);
|
||
}
|
||
};
|
||
const fontCache: { [key: string]: any } = {};
|
||
const ttfCache: { [key: string]: any } = {};
|
||
const fontApiMiddleware: cMiddleware = async (req, res, next) => {
|
||
if (!req.url.startsWith("/api")) return next(req, res);
|
||
res.statusCode = 200;
|
||
res.headers["Content-Type"] = "font/ttf";
|
||
// 创建一个新的 URL 对象(需要一个完整的 URL,必须包含协议和主机)
|
||
const url = new URL(req.url, "http://test.com");
|
||
// 使用 URLSearchParams 来解析查询参数
|
||
const params = new URLSearchParams(url.search);
|
||
// 获取参数的值
|
||
const font = params.get("font") || "";
|
||
const text = params.get("text") || "";
|
||
const path = `font/${font}`;
|
||
const fontType = path.split(".").pop() as "ttf";
|
||
if (ttfCache[req.url]) {
|
||
// @ts-ignore
|
||
res.body = ttfCache[req.url];
|
||
return { req, res };
|
||
}
|
||
const oldFontBuffer = fontCache[path] ?? new Uint8Array(await readFile(path)).buffer;
|
||
fontCache[path] = oldFontBuffer;
|
||
|
||
const outType = "ttf";
|
||
const newFont = await fontSubset(oldFontBuffer, text, {
|
||
outType: outType,
|
||
sourceType: fontType,
|
||
});
|
||
// @ts-ignore
|
||
res.body = newFont;
|
||
ttfCache[req.url] = newFont;
|
||
return { req, res };
|
||
};
|
||
const server = new SimpleHttpServer({ port: 8087 });
|
||
server.use(logMiddleware, corsMiddleware, fontApiMiddleware, staticFileMiddleware);
|
||
|
||
// const main = async () => {
|
||
// // const path = "backend/问藏书房.ttf"; //问藏书房
|
||
// const path = "backend/令东齐伋复刻体.ttf";
|
||
// // const path = "./backend/GoodHood-2.otf";//英文字体
|
||
// const fontType = path.split(".").pop() as "ttf";
|
||
// const oldFontBuffer = new Uint8Array(await readFile(path)).buffer;
|
||
// const outType = "ttf";
|
||
// const newFont = await fontSubset(oldFontBuffer, "abc问书房令东齐伋复刻体", {
|
||
// outType: outType,
|
||
// sourceType: fontType,
|
||
// });
|
||
// writeFile(`./public/font.${outType}`, newFont);
|
||
// };
|