|
|
|
|
| import express from "express";
|
| import bodyParser from "body-parser";
|
| import fetch from "node-fetch";
|
| import FormData from "form-data";
|
| import { PassThrough } from "stream";
|
| import { log } from './config/logger.js';
|
| import fs from 'fs';
|
| import path from 'path';
|
| import { fileURLToPath } from 'url';
|
| import { WebSocketServer } from 'ws';
|
| import { Tail } from 'tail';
|
| import http from 'http';
|
|
|
|
|
| import chatHandler from "./botType/chatHandler.js";
|
| import completionHandler from "./botType/completionHandler.js";
|
| import workflowHandler from "./botType/workflowHandler.js";
|
|
|
|
|
| import {
|
| sanitizeLog,
|
| logRequest,
|
| logResponse,
|
| logApiCall,
|
| generateId,
|
| } from "./botType/utils.js";
|
|
|
|
|
| function parseConfig(authHeader, modelParam) {
|
| log("debug", "开始解析配置", {
|
| authHeader: authHeader ? authHeader.substring(0, 20) + "..." : "No Auth Header",
|
| modelParam,
|
| });
|
|
|
| let config = {};
|
|
|
|
|
| if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
| log("error", "缺少或无效的 Authorization header");
|
| throw new Error("Missing or invalid Authorization header");
|
| }
|
|
|
| const [_, token] = authHeader.split("Bearer ");
|
| const tokenParts = token.split("|");
|
|
|
|
|
| if (tokenParts.length >= 3) {
|
| const [difyApiUrl, apiKey, botType, inputVariable, outputVariable] = tokenParts;
|
| config = {
|
| DIFY_API_URL: difyApiUrl,
|
| API_KEY: apiKey,
|
| BOT_TYPE: botType,
|
| INPUT_VARIABLE: inputVariable || "",
|
| OUTPUT_VARIABLE: outputVariable || "",
|
| };
|
| log("info", "配置解析成功 - 方式一", config);
|
| return config;
|
| }
|
|
|
|
|
| if (tokenParts.length === 1) {
|
| const singleValue = tokenParts[0].trim();
|
|
|
|
|
| if (!modelParam) {
|
| log("error", "缺少 model 参数");
|
| throw new Error("Missing model parameter");
|
| }
|
|
|
| const modelParts = modelParam.split("|");
|
| if (modelParts[0] !== "dify" || modelParts.length < 3) {
|
| log("error", "无效的 model 参数格式");
|
| throw new Error("Invalid model parameter format");
|
| }
|
|
|
|
|
| if (singleValue.length > 0 && !singleValue.includes("http")) {
|
| config.API_KEY = singleValue;
|
| const [_, botType, difyApiUrl, inputVariable, outputVariable] = modelParts;
|
| config.DIFY_API_URL = difyApiUrl;
|
| config.BOT_TYPE = botType;
|
| config.INPUT_VARIABLE = inputVariable || "";
|
| config.OUTPUT_VARIABLE = outputVariable || "";
|
| log("info", "配置解析成功 - 方式二", config);
|
| }
|
|
|
| else {
|
| config.DIFY_API_URL = singleValue;
|
| const [_, apiKey, botType, inputVariable, outputVariable] = modelParts;
|
| config.API_KEY = apiKey;
|
| config.BOT_TYPE = botType;
|
| config.INPUT_VARIABLE = inputVariable || "";
|
| config.OUTPUT_VARIABLE = outputVariable || "";
|
| log("info", "配置解析成功 - 方式三", config);
|
| }
|
| }
|
|
|
|
|
| if (!config.DIFY_API_URL || !config.API_KEY || !config.BOT_TYPE) {
|
| log("error", "缺少必要的配置参数", {
|
| DIFY_API_URL: !!config.DIFY_API_URL,
|
| API_KEY: !!config.API_KEY,
|
| BOT_TYPE: !!config.BOT_TYPE,
|
| config
|
| });
|
| throw new Error("Missing required configuration parameters");
|
| }
|
|
|
| return config;
|
| }
|
|
|
| const app = express();
|
|
|
|
|
| app.use((req, res, next) => {
|
| res.header("Access-Control-Allow-Origin", "*");
|
| res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
| res.header("Access-Control-Allow-Headers", "*");
|
| res.header("Access-Control-Allow-Credentials", true);
|
| res.header("Access-Control-Max-Age", "86400");
|
|
|
| if (req.method === "OPTIONS") {
|
| return res.sendStatus(200);
|
| }
|
| next();
|
| });
|
|
|
|
|
| app.use(express.static('public'));
|
|
|
|
|
| app.use(express.json({ limit: "100mb" }));
|
| app.use(express.urlencoded({ limit: "100mb", extended: true }));
|
| app.use(express.raw({ limit: "100mb" }));
|
|
|
|
|
| app.use((req, res, next) => {
|
| if (process.env.NODE_ENV === 'development' && req.method === "POST") {
|
| log('debug', 'Raw request body', { body: req.body });
|
| }
|
| next();
|
| });
|
|
|
| app.use((req, res, next) => {
|
| if (process.env.NODE_ENV === 'development') {
|
| log('info', 'Incoming request', {
|
| method: req.method,
|
| path: req.path
|
| });
|
| }
|
| next();
|
| });
|
|
|
|
|
| app.get("/", (req, res) => {
|
| res.sendFile(path.join(__dirname, 'public/index.html'));
|
| });
|
|
|
|
|
| app.get("/v1/models", (req, res) => {
|
| const models = {
|
| object: "list",
|
| data: [
|
| {
|
| id: "dify",
|
| object: "model",
|
| owned_by: "dify",
|
| permission: null,
|
| capabilities: {
|
| vision: true,
|
| file_processing: true,
|
| },
|
| },
|
| ],
|
| };
|
| res.json(models);
|
| });
|
|
|
|
|
| app.post("/v1/chat/completions", async (req, res) => {
|
| const requestId = generateId();
|
| const startTime = Date.now();
|
|
|
|
|
| logRequest(req, requestId);
|
|
|
| const authHeader = req.headers.authorization;
|
| if (!authHeader) {
|
| const error = new Error("Missing Authorization header");
|
| log("error", "缺少 Authorization header", {
|
| requestId,
|
| error: error.message,
|
| stack: error.stack,
|
| });
|
| return res.status(401).json({ error: "Missing Authorization header" });
|
| }
|
|
|
| try {
|
|
|
| const config = parseConfig(authHeader, req.body.model);
|
| const botType = config.BOT_TYPE;
|
|
|
| log("debug", "请求参数处理", {
|
| requestId,
|
| botType,
|
| });
|
|
|
|
|
| if (botType === "Chat") {
|
| await chatHandler.handleRequest(req, res, config, requestId, startTime);
|
| } else if (botType === "Completion") {
|
| await completionHandler.handleRequest(
|
| req,
|
| res,
|
| config,
|
| requestId,
|
| startTime
|
| );
|
| } else if (botType === "Workflow") {
|
| await workflowHandler.handleRequest(
|
| req,
|
| res,
|
| config,
|
| requestId,
|
| startTime
|
| );
|
| } else {
|
| log("error", "无效的 bot 类型", { botType });
|
| throw new Error("Invalid bot type in configuration.");
|
| }
|
| } catch (error) {
|
|
|
| log("error", "处理请求时发生错误", {
|
| requestId,
|
| error: {
|
| message: error.message,
|
| stack: error.stack,
|
| name: error.name,
|
| },
|
| timestamp: new Date().toISOString(),
|
| });
|
| res.status(500).json({ error: error.message });
|
| }
|
| });
|
|
|
| const server = http.createServer(app);
|
|
|
| server.listen(process.env.PORT || 3099, () => {
|
| log('info', '服务器启动成功', {
|
| port: process.env.PORT || 3099,
|
| env: process.env.NODE_ENV || 'development'
|
| });
|
| });
|
|
|