mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
122 lines
2.7 KiB
JavaScript
122 lines
2.7 KiB
JavaScript
/**
|
||
* 统一的 CDN Headers 过滤列表
|
||
*
|
||
* 用于各服务在原有过滤逻辑基础上,额外移除 Cloudflare CDN 和代理相关的 headers
|
||
* 避免触发上游 API(如 88code)的安全检查
|
||
*/
|
||
|
||
// Cloudflare CDN headers(橙色云代理模式会添加这些)
|
||
const cdnHeaders = [
|
||
'x-real-ip',
|
||
'x-forwarded-for',
|
||
'x-forwarded-proto',
|
||
'x-forwarded-host',
|
||
'x-forwarded-port',
|
||
'x-accel-buffering',
|
||
'cf-ray',
|
||
'cf-connecting-ip',
|
||
'cf-ipcountry',
|
||
'cf-visitor',
|
||
'cf-request-id',
|
||
'cdn-loop',
|
||
'true-client-ip'
|
||
]
|
||
|
||
/**
|
||
* 为 OpenAI/Responses API 过滤 headers
|
||
* 在原有 skipHeaders 基础上添加 CDN headers
|
||
*/
|
||
function filterForOpenAI(headers) {
|
||
const skipHeaders = [
|
||
'host',
|
||
'content-length',
|
||
'authorization',
|
||
'x-api-key',
|
||
'x-cr-api-key',
|
||
'connection',
|
||
'upgrade',
|
||
'sec-websocket-key',
|
||
'sec-websocket-version',
|
||
'sec-websocket-extensions',
|
||
...cdnHeaders // 添加 CDN headers
|
||
]
|
||
|
||
const filtered = {}
|
||
for (const [key, value] of Object.entries(headers)) {
|
||
if (!skipHeaders.includes(key.toLowerCase())) {
|
||
filtered[key] = value
|
||
}
|
||
}
|
||
return filtered
|
||
}
|
||
|
||
/**
|
||
* 为 Claude/Anthropic API 过滤 headers
|
||
* 使用白名单模式,只允许指定的 headers 通过
|
||
*/
|
||
function filterForClaude(headers) {
|
||
// 白名单模式:只允许以下 headers
|
||
const allowedHeaders = [
|
||
'accept',
|
||
'x-stainless-retry-count',
|
||
'x-stainless-timeout',
|
||
'x-stainless-lang',
|
||
'x-stainless-package-version',
|
||
'x-stainless-os',
|
||
'x-stainless-arch',
|
||
'x-stainless-runtime',
|
||
'x-stainless-runtime-version',
|
||
'x-stainless-helper-method',
|
||
'anthropic-dangerous-direct-browser-access',
|
||
'anthropic-version',
|
||
'x-app',
|
||
'anthropic-beta',
|
||
'accept-language',
|
||
'sec-fetch-mode',
|
||
'accept-encoding',
|
||
'user-agent',
|
||
'content-type',
|
||
'connection'
|
||
]
|
||
|
||
const filtered = {}
|
||
Object.keys(headers || {}).forEach((key) => {
|
||
const lowerKey = key.toLowerCase()
|
||
if (allowedHeaders.includes(lowerKey)) {
|
||
filtered[key] = headers[key]
|
||
}
|
||
})
|
||
|
||
return filtered
|
||
}
|
||
|
||
/**
|
||
* 为 Gemini API 过滤 headers(如果需要转发客户端 headers 时使用)
|
||
* 目前 Gemini 服务不转发客户端 headers,仅提供此方法备用
|
||
*/
|
||
function filterForGemini(headers) {
|
||
const skipHeaders = [
|
||
'host',
|
||
'content-length',
|
||
'authorization',
|
||
'x-api-key',
|
||
'connection',
|
||
...cdnHeaders // 添加 CDN headers
|
||
]
|
||
|
||
const filtered = {}
|
||
for (const [key, value] of Object.entries(headers)) {
|
||
if (!skipHeaders.includes(key.toLowerCase())) {
|
||
filtered[key] = value
|
||
}
|
||
}
|
||
return filtered
|
||
}
|
||
|
||
module.exports = {
|
||
cdnHeaders,
|
||
filterForOpenAI,
|
||
filterForClaude,
|
||
filterForGemini
|
||
}
|