110 lines
3.7 KiB
Plaintext
Raw Permalink Normal View History

2025-05-11 23:06:57 +08:00
/**
* 导入Deno标准库中的HTTP服务器模块
*/
import { serve } from "https://deno.land/std/http/server.ts";
/**
* API映射表定义了路由前缀到实际API端点的映射关系
* 用于将请求转发到相应的第三方服务
*/
const apiMapping = {
'/discord': 'https://discord.com/api', // Discord API
'/telegram': 'https://api.telegram.org', // Telegram API
'/openai': 'https://api.openai.com', // OpenAI API
'/claude': 'https://api.anthropic.com', // Anthropic Claude API
'/gemini': 'https://generativelanguage.googleapis.com', // Google Gemini API
'/meta': 'https://www.meta.ai/api', // Meta AI API
'/groq': 'https://api.groq.com/openai', // Groq API (OpenAI兼容)
'/xai': 'https://api.x.ai', // X.AI API
'/cohere': 'https://api.cohere.ai', // Cohere API
'/huggingface': 'https://api-inference.huggingface.co', // Hugging Face API
'/together': 'https://api.together.xyz', // Together AI API
'/novita': 'https://api.novita.ai', // Novita AI API
'/portkey': 'https://api.portkey.ai', // Portkey API
'/fireworks': 'https://api.fireworks.ai', // Fireworks AI API
'/openrouter': 'https://openrouter.ai/api' // OpenRouter API
};
/**
* 启动HTTP服务器处理所有传入的请求
*/
serve(async (request) => {
// 解析请求URL
const url = new URL(request.url);
const pathname = url.pathname;
// 处理根路径和index.html请求
if (pathname === '/' || pathname === '/index.html') {
return new Response('Service is running!', {
status: 200,
headers: { 'Content-Type': 'text/html' }
});
}
// 处理robots.txt请求禁止搜索引擎爬取
if (pathname === '/robots.txt') {
return new Response('User-agent: *\nDisallow: /', {
status: 200,
headers: { 'Content-Type': 'text/plain' }
});
}
// 从请求路径中提取API前缀和剩余路径
const [prefix, rest] = extractPrefixAndRest(pathname, Object.keys(apiMapping));
if (!prefix) {
return new Response('Not Found', { status: 404 });
}
// 构建目标URL
const targetUrl = `${apiMapping[prefix]}${rest}`;
try {
// 创建新的请求头,只保留允许的头部信息
const headers = new Headers();
const allowedHeaders = ['accept', 'content-type', 'authorization'];
for (const [key, value] of request.headers.entries()) {
if (allowedHeaders.includes(key.toLowerCase())) {
headers.set(key, value);
}
}
// 转发请求到目标API
const response = await fetch(targetUrl, {
method: request.method,
headers: headers,
body: request.body
});
// 设置安全相关的响应头
const responseHeaders = new Headers(response.headers);
responseHeaders.set('X-Content-Type-Options', 'nosniff');
responseHeaders.set('X-Frame-Options', 'DENY');
responseHeaders.set('Referrer-Policy', 'no-referrer');
// 返回API响应
return new Response(response.body, {
status: response.status,
headers: responseHeaders
});
} catch (error) {
// 处理请求错误
console.error('Failed to fetch:', error);
return new Response('Internal Server Error', { status: 500 });
}
});
/**
* 从路径中提取API前缀和剩余部分
* @param {string} pathname - 请求路径
* @param {string[]} prefixes - 可用的API前缀列表
* @returns {[string|null, string|null]} - 返回匹配的前缀和剩余路径,如果没有匹配则返回[null, null]
*/
function extractPrefixAndRest(pathname, prefixes) {
for (const prefix of prefixes) {
if (pathname.startsWith(prefix)) {
return [prefix, pathname.slice(prefix.length)];
}
}
return [null, null];
}