fix: 优化Claude Code User-Agent识别逻辑

- 将字符串匹配改为正则表达式匹配,提高准确性
  - 统一版本号提取正则,支持多段版本号格式
  - 修复isRealClaudeCodeRequest中的User-Agent验证逻辑"
This commit is contained in:
sczheng189
2025-09-04 09:19:39 +08:00
parent 39c49fe2bb
commit 8f08d7843f
2 changed files with 10 additions and 10 deletions

View File

@@ -50,7 +50,7 @@ class ClaudeCodeHeadersService {
if (!userAgent) { if (!userAgent) {
return null return null
} }
const match = userAgent.match(/claude-cli\/(\d+\.\d+\.\d+)/) const match = userAgent.match(/claude-cli\/([\d.]+(?:[a-zA-Z0-9-]*)?)/i)
return match ? match[1] : null return match ? match[1] : null
} }
@@ -113,7 +113,7 @@ class ClaudeCodeHeadersService {
// 检查是否有 user-agent // 检查是否有 user-agent
const userAgent = extractedHeaders['user-agent'] const userAgent = extractedHeaders['user-agent']
if (!userAgent || !userAgent.includes('claude-cli')) { if (!userAgent || !/^claude-cli\/[\d.]+\s+\(/i.test(userAgent)) {
// 不是 Claude Code 的请求,不存储 // 不是 Claude Code 的请求,不存储
return return
} }

View File

@@ -24,7 +24,7 @@ class ClaudeRelayService {
isRealClaudeCodeRequest(requestBody, clientHeaders) { isRealClaudeCodeRequest(requestBody, clientHeaders) {
// 检查 user-agent 是否匹配 Claude Code 格式 // 检查 user-agent 是否匹配 Claude Code 格式
const userAgent = clientHeaders?.['user-agent'] || clientHeaders?.['User-Agent'] || '' const userAgent = clientHeaders?.['user-agent'] || clientHeaders?.['User-Agent'] || ''
const isClaudeCodeUserAgent = /claude-cli\/\d+\.\d+\.\d+/.test(userAgent) const isClaudeCodeUserAgent = /^claude-cli\/[\d.]+\s+\(/i.test(userAgent)
// 检查系统提示词是否包含 Claude Code 标识 // 检查系统提示词是否包含 Claude Code 标识
const hasClaudeCodeSystemPrompt = this._hasClaudeCodeSystemPrompt(requestBody) const hasClaudeCodeSystemPrompt = this._hasClaudeCodeSystemPrompt(requestBody)
@@ -1611,16 +1611,15 @@ class ClaudeRelayService {
const CACHE_KEY = 'claude_code_user_agent:daily' const CACHE_KEY = 'claude_code_user_agent:daily'
const TTL = 90000 // 25小时 const TTL = 90000 // 25小时
// ⚠️ 重要:这里通过 'claude-cli/' 判断是否为 Claude Code 客户端 // ⚠️ 重要:这里通过正则表达式判断是否为 Claude Code 客户端
// 如果未来 Claude Code 的 User-Agent 格式发生变化(不再包含 'claude-cli/' // 如果未来 Claude Code 的 User-Agent 格式发生变化,需要更新这个正则表达式
// 需要更新这个判断条件!
// 当前已知格式claude-cli/1.0.102 (external, cli) // 当前已知格式claude-cli/1.0.102 (external, cli)
const CLAUDE_CODE_UA_IDENTIFIER = 'claude-cli/' const CLAUDE_CODE_UA_PATTERN = /^claude-cli\/[\d.]+\s+\(/i
const clientUA = clientHeaders?.['user-agent'] || clientHeaders?.['User-Agent'] const clientUA = clientHeaders?.['user-agent'] || clientHeaders?.['User-Agent']
let cachedUA = await redis.client.get(CACHE_KEY) let cachedUA = await redis.client.get(CACHE_KEY)
if (clientUA?.includes(CLAUDE_CODE_UA_IDENTIFIER)) { if (clientUA && CLAUDE_CODE_UA_PATTERN.test(clientUA)) {
if (!cachedUA) { if (!cachedUA) {
// 没有缓存,直接存储 // 没有缓存,直接存储
await redis.client.setex(CACHE_KEY, TTL, clientUA) await redis.client.setex(CACHE_KEY, TTL, clientUA)
@@ -1648,8 +1647,9 @@ class ClaudeRelayService {
compareClaudeCodeVersions(newUA, cachedUA) { compareClaudeCodeVersions(newUA, cachedUA) {
try { try {
// 提取版本号claude-cli/1.0.102 (external, cli) -> 1.0.102 // 提取版本号claude-cli/1.0.102 (external, cli) -> 1.0.102
const newVersionMatch = newUA.match(/claude-cli\/([0-9]+\.[0-9]+\.[0-9]+)/) // 支持多段版本号格式,如 1.0.102、2.1.0.beta1 等
const cachedVersionMatch = cachedUA.match(/claude-cli\/([0-9]+\.[0-9]+\.[0-9]+)/) const newVersionMatch = newUA.match(/claude-cli\/([\d.]+(?:[a-zA-Z0-9-]*)?)/i)
const cachedVersionMatch = cachedUA.match(/claude-cli\/([\d.]+(?:[a-zA-Z0-9-]*)?)/i)
if (!newVersionMatch || !cachedVersionMatch) { if (!newVersionMatch || !cachedVersionMatch) {
// 无法解析版本号,优先使用新的 // 无法解析版本号,优先使用新的