feat(lpt-ai):新增 /fetch-title 网页标题抓取接口
POST /fetch-title { url } → { url, title }
- 服务端 fetch 目标页面,正则提取 <title> 标签
- 10 秒超时,抓取失败时返回 title: null
- 请求日志记录到 logStore
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import { isAvailable, loadConfig } from "../llm/client.js";
|
||||
import { createTask, getTask, type TaskType } from "../task-queue.js";
|
||||
import { logStore } from "../admin/store.js";
|
||||
|
||||
export async function aiRoutes(app: FastifyInstance): Promise<void> {
|
||||
const config = loadConfig();
|
||||
@@ -39,4 +40,48 @@ export async function aiRoutes(app: FastifyInstance): Promise<void> {
|
||||
}
|
||||
return task;
|
||||
});
|
||||
|
||||
/** 抓取网页标题 */
|
||||
app.post<{ Body: { url: string } }>("/fetch-title", async (request, reply) => {
|
||||
const { url } = request.body ?? {};
|
||||
const t0 = Date.now();
|
||||
|
||||
if (!url || typeof url !== "string" || (!url.startsWith("http://") && !url.startsWith("https://"))) {
|
||||
return reply.status(400).send({ error: "无效的 URL" });
|
||||
}
|
||||
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), 10_000);
|
||||
const response = await fetch(url, { signal: controller.signal });
|
||||
clearTimeout(timer);
|
||||
|
||||
const html = await response.text();
|
||||
const match = html.match(/<title[^>]*>([^<]+)<\/title>/i);
|
||||
const title = match ? match[1].trim() : null;
|
||||
|
||||
logStore.add({
|
||||
timestamp: new Date().toISOString(),
|
||||
endpoint: "/fetch-title",
|
||||
model: "",
|
||||
durationMs: Date.now() - t0,
|
||||
status: 200,
|
||||
requestBody: { url },
|
||||
responseBody: { url, title },
|
||||
});
|
||||
return { url, title };
|
||||
} catch (err) {
|
||||
logStore.add({
|
||||
timestamp: new Date().toISOString(),
|
||||
endpoint: "/fetch-title",
|
||||
model: "",
|
||||
durationMs: Date.now() - t0,
|
||||
status: 502,
|
||||
requestBody: { url },
|
||||
responseBody: { url, title: null },
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
});
|
||||
return { url, title: null };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user