mirror of
https://github.com/xxnuo/MTranServer.git
synced 2026-06-02 12:13:23 +08:00
Init
This commit is contained in:
86
js/mts.js
Executable file
86
js/mts.js
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fastify = require('fastify');
|
||||
const cors = require('@fastify/cors');
|
||||
const { getConfig, validateToken } = require('./utils/config');
|
||||
const { authenticate, errorHandler } = require('./utils/middleware');
|
||||
const { getSupportedLanguages, preloadModel, shutdown } = require('./utils/translator');
|
||||
const registerCoreRoutes = require('./routes/core');
|
||||
const registerTranslateRoutes = require('./routes/translate');
|
||||
const registerPluginRoutes = require('./routes/plugins');
|
||||
|
||||
// 获取配置
|
||||
const config = getConfig();
|
||||
|
||||
// 创建Fastify实例
|
||||
const server = fastify({
|
||||
logger: {
|
||||
level: config.logLevel,
|
||||
transport: {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
translateTime: 'HH:MM:ss Z',
|
||||
ignore: 'pid,hostname'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 注册CORS中间件
|
||||
server.register(cors, {
|
||||
origin: true,
|
||||
methods: ['GET', 'POST', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'Key']
|
||||
});
|
||||
|
||||
// 设置错误处理器
|
||||
server.setErrorHandler(errorHandler);
|
||||
|
||||
// 路由选项
|
||||
const routeOptions = {
|
||||
authenticate: authenticate,
|
||||
validateToken: validateToken
|
||||
};
|
||||
|
||||
// 注册路由
|
||||
server.register(registerCoreRoutes, routeOptions);
|
||||
server.register(registerTranslateRoutes, routeOptions);
|
||||
server.register(registerPluginRoutes, routeOptions);
|
||||
|
||||
// 启动服务器
|
||||
async function start() {
|
||||
try {
|
||||
// 输出服务信息
|
||||
console.log(`Service port: ${config.port}`);
|
||||
|
||||
// 获取支持的语言列表
|
||||
const languages = getSupportedLanguages();
|
||||
|
||||
// 预加载常用语言对
|
||||
// await preloadModel('en', 'zh-Hans');
|
||||
|
||||
// 监听端口
|
||||
await server.listen({ port: config.port, host: config.host });
|
||||
} catch (err) {
|
||||
server.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进程退出
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Shutting down server...');
|
||||
await shutdown();
|
||||
await server.close();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('Shutting down server...');
|
||||
await shutdown();
|
||||
await server.close();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// 启动服务器
|
||||
start();
|
||||
40
js/routes/core.js
Normal file
40
js/routes/core.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const { getVersion } = require('../utils/config');
|
||||
const { getLoadedModels } = require('../utils/translator');
|
||||
|
||||
/**
|
||||
* 注册核心路由
|
||||
* @param {Object} fastify Fastify实例
|
||||
* @param {Object} options 选项
|
||||
*/
|
||||
function registerCoreRoutes(fastify, options) {
|
||||
// 版本信息
|
||||
fastify.get('/version', async (request, reply) => {
|
||||
return { version: getVersion() };
|
||||
});
|
||||
|
||||
// 健康检查
|
||||
fastify.get('/health', async (request, reply) => {
|
||||
return { status: 'ok' };
|
||||
});
|
||||
|
||||
// 心跳检查
|
||||
fastify.get('/__heartbeat__', async (request, reply) => {
|
||||
reply.type('text/plain');
|
||||
return 'Ready';
|
||||
});
|
||||
|
||||
// 负载均衡心跳检查
|
||||
fastify.get('/__lbheartbeat__', async (request, reply) => {
|
||||
reply.type('text/plain');
|
||||
return 'Ready';
|
||||
});
|
||||
|
||||
// 获取已加载的模型列表
|
||||
fastify.get('/models', {
|
||||
preHandler: options.authenticate
|
||||
}, async (request, reply) => {
|
||||
return { models: getLoadedModels() };
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = registerCoreRoutes;
|
||||
90
js/routes/plugins.js
Normal file
90
js/routes/plugins.js
Normal file
@@ -0,0 +1,90 @@
|
||||
const { translate, batchTranslate } = require('../utils/translator');
|
||||
|
||||
/**
|
||||
* 注册翻译插件兼容路由
|
||||
* @param {Object} fastify Fastify实例
|
||||
* @param {Object} options 选项
|
||||
*/
|
||||
function registerPluginRoutes(fastify, options) {
|
||||
// 沉浸式翻译插件API
|
||||
fastify.post('/imme', async (request, reply) => {
|
||||
// 验证token
|
||||
const token = request.query.token;
|
||||
if (!options.validateToken(token)) {
|
||||
return reply.code(401).send({ error: 'Unauthorized', message: 'Invalid or missing API token' });
|
||||
}
|
||||
|
||||
try {
|
||||
const { source_lang, target_lang, text, texts } = request.body;
|
||||
|
||||
// 处理批量翻译
|
||||
if (Array.isArray(texts) && texts.length > 0) {
|
||||
const results = await batchTranslate(texts, source_lang || 'auto', target_lang || 'zh-Hans');
|
||||
return { data: results };
|
||||
}
|
||||
|
||||
// 处理单个文本翻译
|
||||
if (text) {
|
||||
const result = await translate(text, source_lang || 'auto', target_lang || 'zh-Hans');
|
||||
return { data: result };
|
||||
}
|
||||
|
||||
return reply.code(400).send({ error: 'BadRequest', message: 'Missing text or texts parameter' });
|
||||
} catch (error) {
|
||||
return reply.code(500).send({ error: 'TranslationError', message: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 简约翻译插件API
|
||||
fastify.post('/kiss', async (request, reply) => {
|
||||
// 验证token
|
||||
const token = request.headers.key;
|
||||
if (!options.validateToken(token)) {
|
||||
return reply.code(401).send({ error: 'Unauthorized', message: 'Invalid or missing API token' });
|
||||
}
|
||||
|
||||
try {
|
||||
const { from, to, text, texts } = request.body;
|
||||
|
||||
// 处理批量翻译
|
||||
if (Array.isArray(texts) && texts.length > 0) {
|
||||
const results = await batchTranslate(texts, from || 'auto', to || 'zh-Hans');
|
||||
return { code: 200, text: results.join('\n') };
|
||||
}
|
||||
|
||||
// 处理单个文本翻译
|
||||
if (text) {
|
||||
const result = await translate(text, from || 'auto', to || 'zh-Hans');
|
||||
return { code: 200, text: result };
|
||||
}
|
||||
|
||||
return reply.code(400).send({ code: 400, error: 'Missing text or texts parameter' });
|
||||
} catch (error) {
|
||||
return reply.code(500).send({ code: 500, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 划词翻译插件API
|
||||
fastify.post('/hcfy', async (request, reply) => {
|
||||
// 验证token
|
||||
const token = request.query.token;
|
||||
if (!options.validateToken(token)) {
|
||||
return reply.code(401).send({ error: 'Unauthorized', message: 'Invalid or missing API token' });
|
||||
}
|
||||
|
||||
try {
|
||||
const { text, from, to } = request.body;
|
||||
|
||||
if (!text) {
|
||||
return reply.code(400).send({ error: 'BadRequest', message: 'Missing text parameter' });
|
||||
}
|
||||
|
||||
const result = await translate(text, from || 'auto', to || 'zh-Hans');
|
||||
return { translation: result };
|
||||
} catch (error) {
|
||||
return reply.code(500).send({ error: 'TranslationError', message: error.message });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = registerPluginRoutes;
|
||||
104
js/routes/translate.js
Normal file
104
js/routes/translate.js
Normal file
@@ -0,0 +1,104 @@
|
||||
const { translate, batchTranslate } = require('../utils/translator');
|
||||
|
||||
/**
|
||||
* 注册翻译路由
|
||||
* @param {Object} fastify Fastify实例
|
||||
* @param {Object} options 选项
|
||||
*/
|
||||
function registerTranslateRoutes(fastify, options) {
|
||||
// 普通翻译API
|
||||
fastify.post('/translate', {
|
||||
preHandler: options.authenticate,
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['from', 'to', 'text'],
|
||||
properties: {
|
||||
from: { type: 'string' },
|
||||
to: { type: 'string' },
|
||||
text: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const { from, to, text } = request.body;
|
||||
|
||||
try {
|
||||
const result = await translate(text, from, to);
|
||||
return { result };
|
||||
} catch (error) {
|
||||
reply.code(500).send({
|
||||
error: 'TranslationError',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 批量翻译API
|
||||
fastify.post('/translate/batch', {
|
||||
preHandler: options.authenticate,
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['from', 'to', 'texts'],
|
||||
properties: {
|
||||
from: { type: 'string' },
|
||||
to: { type: 'string' },
|
||||
texts: {
|
||||
type: 'array',
|
||||
items: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const { from, to, texts } = request.body;
|
||||
|
||||
try {
|
||||
const results = await batchTranslate(texts, from, to);
|
||||
return { results };
|
||||
} catch (error) {
|
||||
reply.code(500).send({
|
||||
error: 'BatchTranslationError',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Google翻译兼容API
|
||||
fastify.post('/language/translate/v2', {
|
||||
preHandler: options.authenticate,
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['q', 'source', 'target'],
|
||||
properties: {
|
||||
q: { type: 'string' },
|
||||
source: { type: 'string' },
|
||||
target: { type: 'string' },
|
||||
format: { type: 'string', default: 'text' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
const { q, source, target } = request.body;
|
||||
|
||||
try {
|
||||
const translatedText = await translate(q, source, target);
|
||||
return {
|
||||
data: {
|
||||
translations: [
|
||||
{ translatedText }
|
||||
]
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
reply.code(500).send({
|
||||
error: 'TranslationError',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = registerTranslateRoutes;
|
||||
48
js/utils/config.js
Normal file
48
js/utils/config.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 配置管理模块
|
||||
*/
|
||||
|
||||
// 默认配置
|
||||
const defaultConfig = {
|
||||
port: process.env.PORT || 8989,
|
||||
host: process.env.HOST || '0.0.0.0',
|
||||
apiToken: process.env.CORE_API_TOKEN || '',
|
||||
logLevel: process.env.LOG_LEVEL || 'info'
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取配置
|
||||
* @returns {Object} 配置对象
|
||||
*/
|
||||
function getConfig() {
|
||||
return { ...defaultConfig };
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证API令牌
|
||||
* @param {string} token 待验证的令牌
|
||||
* @returns {boolean} 是否有效
|
||||
*/
|
||||
function validateToken(token) {
|
||||
// 如果未设置API令牌,则不需要验证
|
||||
if (!defaultConfig.apiToken) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return token === defaultConfig.apiToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务器版本
|
||||
* @returns {string} 版本号
|
||||
*/
|
||||
function getVersion() {
|
||||
const packageJson = require('../../package.json');
|
||||
return packageJson.version || 'unknown';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getConfig,
|
||||
validateToken,
|
||||
getVersion
|
||||
};
|
||||
40
js/utils/middleware.js
Normal file
40
js/utils/middleware.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const { validateToken } = require('./config');
|
||||
|
||||
/**
|
||||
* 认证中间件
|
||||
* @param {Object} request Fastify请求对象
|
||||
* @param {Object} reply Fastify响应对象
|
||||
* @param {Function} done 完成回调
|
||||
*/
|
||||
function authenticate(request, reply, done) {
|
||||
const authHeader = request.headers.authorization;
|
||||
const token = request.query.token;
|
||||
|
||||
// 检查Authorization头或URL中的token参数
|
||||
if (validateToken(authHeader) || validateToken(token)) {
|
||||
done();
|
||||
} else {
|
||||
reply.code(401).send({ error: 'Unauthorized', message: 'Invalid or missing API token' });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误处理中间件
|
||||
* @param {Error} error 错误对象
|
||||
* @param {Object} request Fastify请求对象
|
||||
* @param {Object} reply Fastify响应对象
|
||||
*/
|
||||
function errorHandler(error, request, reply) {
|
||||
console.error(`Error processing request: ${error.message}`);
|
||||
|
||||
// 返回适当的错误响应
|
||||
reply.code(error.statusCode || 500).send({
|
||||
error: error.name || 'InternalServerError',
|
||||
message: error.message || 'An unknown error occurred'
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
authenticate,
|
||||
errorHandler
|
||||
};
|
||||
82
js/utils/translator.js
Normal file
82
js/utils/translator.js
Normal file
@@ -0,0 +1,82 @@
|
||||
const Translator = require("@mtran/core");
|
||||
|
||||
// 缓存已加载的模型
|
||||
const loadedModels = new Set();
|
||||
|
||||
/**
|
||||
* 获取支持的语言列表
|
||||
* @returns {Array} 支持的语言列表
|
||||
*/
|
||||
function getSupportedLanguages() {
|
||||
return Translator.GetSupportLanguages();
|
||||
}
|
||||
|
||||
/**
|
||||
* 预加载翻译模型
|
||||
* @param {string} from 源语言
|
||||
* @param {string} to 目标语言
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function preloadModel(from, to) {
|
||||
const modelKey = `${from}_${to}`;
|
||||
if (!loadedModels.has(modelKey)) {
|
||||
await Translator.Preload(from, to);
|
||||
loadedModels.add(modelKey);
|
||||
console.log(`Successfully loaded model for language pair: ${modelKey}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻译文本
|
||||
* @param {string} text 要翻译的文本
|
||||
* @param {string} from 源语言
|
||||
* @param {string} to 目标语言
|
||||
* @returns {Promise<string>} 翻译结果
|
||||
*/
|
||||
async function translate(text, from, to) {
|
||||
// 如果模型未加载,先加载模型
|
||||
await preloadModel(from, to);
|
||||
return Translator.Translate(text, from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量翻译文本
|
||||
* @param {string[]} texts 要翻译的文本数组
|
||||
* @param {string} from 源语言
|
||||
* @param {string} to 目标语言
|
||||
* @returns {Promise<string[]>} 翻译结果数组
|
||||
*/
|
||||
async function batchTranslate(texts, from, to) {
|
||||
// 如果模型未加载,先加载模型
|
||||
await preloadModel(from, to);
|
||||
|
||||
// 并行处理翻译请求
|
||||
const promises = texts.map(text => Translator.Translate(text, from, to));
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭翻译引擎
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function shutdown() {
|
||||
await Translator.Shutdown();
|
||||
console.log("Translation engine shutdown complete");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已加载的模型列表
|
||||
* @returns {string[]} 已加载的模型列表
|
||||
*/
|
||||
function getLoadedModels() {
|
||||
return Array.from(loadedModels);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSupportedLanguages,
|
||||
preloadModel,
|
||||
translate,
|
||||
batchTranslate,
|
||||
shutdown,
|
||||
getLoadedModels
|
||||
};
|
||||
@@ -3,9 +3,9 @@
|
||||
"homepage": "https://github.com/xxnuo",
|
||||
"version": "3.0.0",
|
||||
"type": "commonjs",
|
||||
"main": "dist/mts.js",
|
||||
"main": "js/mts.js",
|
||||
"bin": {
|
||||
"mt": "dist/mts.js"
|
||||
"mt": "js/mts.js"
|
||||
},
|
||||
"keywords": [
|
||||
"translation",
|
||||
@@ -21,6 +21,9 @@
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mtran/core": "file:packages/mtran-core.tgz"
|
||||
"@fastify/cors": "^11.0.1",
|
||||
"@mtran/core": "file:packages/mtran-core.tgz",
|
||||
"fastify": "^5.4.0",
|
||||
"pino-pretty": "^13.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
25
start.sh
Executable file
25
start.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 翻译服务器启动脚本
|
||||
|
||||
# 获取脚本所在目录的绝对路径
|
||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
|
||||
# 切换到脚本所在目录
|
||||
cd "$SCRIPT_DIR" || exit 1
|
||||
|
||||
# 检查是否设置了环境变量
|
||||
if [ -z "$PORT" ]; then
|
||||
export PORT=8989
|
||||
fi
|
||||
|
||||
if [ -z "$HOST" ]; then
|
||||
export HOST=0.0.0.0
|
||||
fi
|
||||
|
||||
# 启动服务
|
||||
echo "Starting MTranServer..."
|
||||
node js/mts.js
|
||||
|
||||
# 脚本结束
|
||||
exit 0
|
||||
36
test.sh
Executable file
36
test.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 测试运行脚本
|
||||
|
||||
# 获取脚本所在目录的绝对路径
|
||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
|
||||
# 切换到脚本所在目录
|
||||
cd "$SCRIPT_DIR" || exit 1
|
||||
|
||||
# 设置环境变量
|
||||
export HOST=${HOST:-localhost}
|
||||
export PORT=${PORT:-8989}
|
||||
export CORE_API_TOKEN=${CORE_API_TOKEN:-}
|
||||
|
||||
# 显示测试环境
|
||||
echo "测试环境:"
|
||||
echo "HOST: $HOST"
|
||||
echo "PORT: $PORT"
|
||||
echo "TOKEN: ${CORE_API_TOKEN:-(未设置)}"
|
||||
echo ""
|
||||
|
||||
# 运行测试
|
||||
echo "=== 运行核心API测试 ==="
|
||||
node tests/core-api.js
|
||||
echo ""
|
||||
|
||||
echo "=== 运行翻译API测试 ==="
|
||||
node tests/translate-api.js
|
||||
echo ""
|
||||
|
||||
echo "=== 运行翻译插件兼容API测试 ==="
|
||||
node tests/plugin-api.js
|
||||
echo ""
|
||||
|
||||
echo "所有测试完成!"
|
||||
184
tests/core-api.js
Executable file
184
tests/core-api.js
Executable file
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* 测试核心API
|
||||
* 包括版本、健康检查、心跳检查和模型列表API
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
|
||||
// 配置
|
||||
const config = {
|
||||
host: process.env.HOST || 'localhost',
|
||||
port: process.env.PORT || 8989,
|
||||
token: process.env.CORE_API_TOKEN || ''
|
||||
};
|
||||
|
||||
// 测试版本API
|
||||
function testVersion() {
|
||||
console.log('测试版本API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/version',
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${data}`);
|
||||
console.log('版本API测试完成\n');
|
||||
|
||||
// 测试下一个API
|
||||
testHealth();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`版本API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试健康检查API
|
||||
function testHealth() {
|
||||
console.log('测试健康检查API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/health',
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${data}`);
|
||||
console.log('健康检查API测试完成\n');
|
||||
|
||||
// 测试下一个API
|
||||
testHeartbeat();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`健康检查API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试心跳检查API
|
||||
function testHeartbeat() {
|
||||
console.log('测试心跳检查API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/__heartbeat__',
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${data}`);
|
||||
console.log('心跳检查API测试完成\n');
|
||||
|
||||
// 测试下一个API
|
||||
testLBHeartbeat();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`心跳检查API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试负载均衡心跳检查API
|
||||
function testLBHeartbeat() {
|
||||
console.log('测试负载均衡心跳检查API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/__lbheartbeat__',
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${data}`);
|
||||
console.log('负载均衡心跳检查API测试完成\n');
|
||||
|
||||
// 测试下一个API
|
||||
testModels();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`负载均衡心跳检查API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试模型列表API
|
||||
function testModels() {
|
||||
console.log('测试模型列表API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/models',
|
||||
method: 'GET',
|
||||
headers: {}
|
||||
};
|
||||
|
||||
// 如果有token,添加到请求头
|
||||
if (config.token) {
|
||||
options.headers['Authorization'] = config.token;
|
||||
}
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${data}`);
|
||||
console.log('模型列表API测试完成\n');
|
||||
|
||||
console.log('所有核心API测试完成');
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`模型列表API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 开始测试
|
||||
console.log('开始测试核心API...\n');
|
||||
testVersion();
|
||||
241
tests/plugin-api.js
Executable file
241
tests/plugin-api.js
Executable file
@@ -0,0 +1,241 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* 测试翻译插件兼容API
|
||||
* 包括沉浸式翻译、简约翻译和划词翻译API
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
|
||||
// 配置
|
||||
const config = {
|
||||
host: process.env.HOST || 'localhost',
|
||||
port: process.env.PORT || 8989,
|
||||
token: process.env.CORE_API_TOKEN || ''
|
||||
};
|
||||
|
||||
// 测试沉浸式翻译API
|
||||
function testImmeTranslate() {
|
||||
console.log('测试沉浸式翻译API...');
|
||||
const tokenParam = config.token ? `?token=${config.token}` : '';
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: `/imme${tokenParam}`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
const data = JSON.stringify({
|
||||
source_lang: 'en',
|
||||
target_lang: 'zh-Hans',
|
||||
text: 'Hello, world!'
|
||||
});
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let responseData = '';
|
||||
res.on('data', (chunk) => {
|
||||
responseData += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${responseData}`);
|
||||
console.log('沉浸式翻译API测试完成\n');
|
||||
|
||||
// 测试批量翻译
|
||||
testImmeBatchTranslate();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`沉浸式翻译API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试沉浸式翻译批量API
|
||||
function testImmeBatchTranslate() {
|
||||
console.log('测试沉浸式翻译批量API...');
|
||||
const tokenParam = config.token ? `?token=${config.token}` : '';
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: `/imme${tokenParam}`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
const data = JSON.stringify({
|
||||
source_lang: 'en',
|
||||
target_lang: 'zh-Hans',
|
||||
texts: ['Hello, world!', 'How are you?']
|
||||
});
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let responseData = '';
|
||||
res.on('data', (chunk) => {
|
||||
responseData += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${responseData}`);
|
||||
console.log('沉浸式翻译批量API测试完成\n');
|
||||
|
||||
// 测试下一个API
|
||||
testKissTranslate();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`沉浸式翻译批量API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试简约翻译API
|
||||
function testKissTranslate() {
|
||||
console.log('测试简约翻译API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/kiss',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
// 如果有token,添加到请求头
|
||||
if (config.token) {
|
||||
options.headers['Key'] = config.token;
|
||||
}
|
||||
|
||||
const data = JSON.stringify({
|
||||
from: 'en',
|
||||
to: 'zh-Hans',
|
||||
text: 'Hello, world!'
|
||||
});
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let responseData = '';
|
||||
res.on('data', (chunk) => {
|
||||
responseData += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${responseData}`);
|
||||
console.log('简约翻译API测试完成\n');
|
||||
|
||||
// 测试批量翻译
|
||||
testKissBatchTranslate();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`简约翻译API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试简约翻译批量API
|
||||
function testKissBatchTranslate() {
|
||||
console.log('测试简约翻译批量API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/kiss',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
// 如果有token,添加到请求头
|
||||
if (config.token) {
|
||||
options.headers['Key'] = config.token;
|
||||
}
|
||||
|
||||
const data = JSON.stringify({
|
||||
from: 'en',
|
||||
to: 'zh-Hans',
|
||||
texts: ['Hello, world!', 'How are you?']
|
||||
});
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let responseData = '';
|
||||
res.on('data', (chunk) => {
|
||||
responseData += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${responseData}`);
|
||||
console.log('简约翻译批量API测试完成\n');
|
||||
|
||||
// 测试下一个API
|
||||
testHcfyTranslate();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`简约翻译批量API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试划词翻译API
|
||||
function testHcfyTranslate() {
|
||||
console.log('测试划词翻译API...');
|
||||
const tokenParam = config.token ? `?token=${config.token}` : '';
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: `/hcfy${tokenParam}`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
const data = JSON.stringify({
|
||||
text: 'Hello, world!',
|
||||
from: 'en',
|
||||
to: 'zh-Hans'
|
||||
});
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let responseData = '';
|
||||
res.on('data', (chunk) => {
|
||||
responseData += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${responseData}`);
|
||||
console.log('划词翻译API测试完成\n');
|
||||
|
||||
console.log('所有翻译插件兼容API测试完成');
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`划词翻译API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 开始测试
|
||||
console.log('开始测试翻译插件兼容API...\n');
|
||||
testImmeTranslate();
|
||||
160
tests/translate-api.js
Executable file
160
tests/translate-api.js
Executable file
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* 测试翻译API
|
||||
* 包括普通翻译、批量翻译和Google翻译兼容API
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
|
||||
// 配置
|
||||
const config = {
|
||||
host: process.env.HOST || 'localhost',
|
||||
port: process.env.PORT || 8989,
|
||||
token: process.env.CORE_API_TOKEN || ''
|
||||
};
|
||||
|
||||
// 测试普通翻译API
|
||||
function testTranslate() {
|
||||
console.log('测试普通翻译API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/translate',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
// 如果有token,添加到请求头
|
||||
if (config.token) {
|
||||
options.headers['Authorization'] = config.token;
|
||||
}
|
||||
|
||||
const data = JSON.stringify({
|
||||
from: 'en',
|
||||
to: 'zh-Hans',
|
||||
text: 'Hello, world!'
|
||||
});
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let responseData = '';
|
||||
res.on('data', (chunk) => {
|
||||
responseData += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${responseData}`);
|
||||
console.log('普通翻译API测试完成\n');
|
||||
|
||||
// 测试下一个API
|
||||
testBatchTranslate();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`普通翻译API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试批量翻译API
|
||||
function testBatchTranslate() {
|
||||
console.log('测试批量翻译API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/translate/batch',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
// 如果有token,添加到请求头
|
||||
if (config.token) {
|
||||
options.headers['Authorization'] = config.token;
|
||||
}
|
||||
|
||||
const data = JSON.stringify({
|
||||
from: 'en',
|
||||
to: 'zh-Hans',
|
||||
texts: ['Hello, world!', 'How are you?']
|
||||
});
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let responseData = '';
|
||||
res.on('data', (chunk) => {
|
||||
responseData += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${responseData}`);
|
||||
console.log('批量翻译API测试完成\n');
|
||||
|
||||
// 测试下一个API
|
||||
testGoogleTranslate();
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`批量翻译API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 测试Google翻译兼容API
|
||||
function testGoogleTranslate() {
|
||||
console.log('测试Google翻译兼容API...');
|
||||
const options = {
|
||||
hostname: config.host,
|
||||
port: config.port,
|
||||
path: '/language/translate/v2',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
// 如果有token,添加到请求头
|
||||
if (config.token) {
|
||||
options.headers['Authorization'] = config.token;
|
||||
}
|
||||
|
||||
const data = JSON.stringify({
|
||||
q: 'The Great Pyramid of Giza',
|
||||
source: 'en',
|
||||
target: 'zh-Hans',
|
||||
format: 'text'
|
||||
});
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
let responseData = '';
|
||||
res.on('data', (chunk) => {
|
||||
responseData += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
console.log(`状态码: ${res.statusCode}`);
|
||||
console.log(`响应数据: ${responseData}`);
|
||||
console.log('Google翻译兼容API测试完成\n');
|
||||
|
||||
console.log('所有翻译API测试完成');
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`Google翻译兼容API测试出错: ${error.message}`);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 开始测试
|
||||
console.log('开始测试翻译API...\n');
|
||||
testTranslate();
|
||||
Reference in New Issue
Block a user