fix: add missing fetch timeouts across server API layer
Prevent potential hangs from fetch calls without AbortSignal: - heicode-auth.ts: token exchange (15s) - heicode-tasks.ts: forwardJson upstream calls (60s) - createDirectConnectSession.ts: session creation (15s) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -162,6 +162,7 @@ export async function handleHeicodeAuthApi(
|
|||||||
const upstream = await fetch(`${mcpBase}/api/user/heicode/balance`, {
|
const upstream = await fetch(`${mcpBase}/api/user/heicode/balance`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Authorization': `Bearer ${active.mcpAuth.accessToken}` },
|
headers: { 'Authorization': `Bearer ${active.mcpAuth.accessToken}` },
|
||||||
|
signal: AbortSignal.timeout(15_000),
|
||||||
})
|
})
|
||||||
// Happy path — mcp-server knows the user.
|
// Happy path — mcp-server knows the user.
|
||||||
if (upstream.ok) {
|
if (upstream.ok) {
|
||||||
@@ -179,6 +180,7 @@ export async function handleHeicodeAuthApi(
|
|||||||
const self = await fetch(`${heicodeBase}/api/user/self`, {
|
const self = await fetch(`${heicodeBase}/api/user/self`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Authorization': `Bearer ${active.apiKey}` },
|
headers: { 'Authorization': `Bearer ${active.apiKey}` },
|
||||||
|
signal: AbortSignal.timeout(15_000),
|
||||||
})
|
})
|
||||||
if (self.ok) {
|
if (self.ok) {
|
||||||
const json = await self.json() as {
|
const json = await self.json() as {
|
||||||
@@ -836,6 +838,7 @@ async function exchangeCodeForToken(input: {
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||||
body: body.toString(),
|
body: body.toString(),
|
||||||
|
signal: AbortSignal.timeout(15_000),
|
||||||
})
|
})
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(`token 交换失败: ${res.status} ${res.statusText}`)
|
throw new Error(`token 交换失败: ${res.status} ${res.statusText}`)
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ async function forwardJson(
|
|||||||
...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),
|
...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),
|
||||||
},
|
},
|
||||||
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
||||||
|
signal: AbortSignal.timeout(60_000),
|
||||||
}
|
}
|
||||||
let upstream: Response
|
let upstream: Response
|
||||||
try {
|
try {
|
||||||
@@ -96,6 +97,7 @@ async function forwardSse(path: string): Promise<Response> {
|
|||||||
Accept: 'text/event-stream',
|
Accept: 'text/event-stream',
|
||||||
'Cache-Control': 'no-cache',
|
'Cache-Control': 'no-cache',
|
||||||
},
|
},
|
||||||
|
signal: AbortSignal.timeout(600_000),
|
||||||
})
|
})
|
||||||
if (!upstream.ok || !upstream.body) {
|
if (!upstream.ok || !upstream.body) {
|
||||||
const text = await upstream.text().catch(() => '')
|
const text = await upstream.text().catch(() => '')
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export async function createDirectConnectSession({
|
|||||||
dangerously_skip_permissions: true,
|
dangerously_skip_permissions: true,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
signal: AbortSignal.timeout(15_000),
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new DirectConnectError(
|
throw new DirectConnectError(
|
||||||
|
|||||||
Reference in New Issue
Block a user