mirror of
https://github.com/langgenius/dify.git
synced 2026-06-11 19:14:34 +08:00
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
86 lines
2.5 KiB
TypeScript
86 lines
2.5 KiB
TypeScript
import type { BaseError } from '@/errors/base'
|
|
import { newError } from '@/errors/base'
|
|
import { ErrorCode } from '@/errors/codes'
|
|
import { redactBearer } from './sanitize'
|
|
|
|
type WireFields = {
|
|
code?: string
|
|
message?: string
|
|
hint?: string
|
|
}
|
|
|
|
type WireEnvelope = WireFields & {
|
|
error?: WireFields
|
|
}
|
|
|
|
async function readBody(response: Response): Promise<{ raw: string, parsed?: WireEnvelope }> {
|
|
let raw = ''
|
|
try {
|
|
raw = await response.text()
|
|
}
|
|
catch {
|
|
return { raw: '' }
|
|
}
|
|
if (raw === '')
|
|
return { raw }
|
|
try {
|
|
return { raw, parsed: JSON.parse(raw) as WireEnvelope }
|
|
}
|
|
catch {
|
|
return { raw }
|
|
}
|
|
}
|
|
|
|
export async function classifyResponse(request: Request, response: Response): Promise<BaseError> {
|
|
const { parsed } = await readBody(response.clone())
|
|
const wire: WireFields = parsed?.error ?? parsed ?? {}
|
|
const status = response.status
|
|
const url = redactBearer(response.url || request.url)
|
|
const method = request.method
|
|
|
|
if (status === 401) {
|
|
return newError(
|
|
ErrorCode.AuthExpired,
|
|
wire.message ?? 'session expired or revoked',
|
|
)
|
|
.withHint(wire.hint ?? 'run \'difyctl auth login\' to sign in again')
|
|
.withHttpStatus(status)
|
|
.withRequest(method, url)
|
|
}
|
|
|
|
if (status >= 500) {
|
|
return newError(
|
|
ErrorCode.Server5xx,
|
|
wire.message ?? `server error (HTTP ${status})`,
|
|
)
|
|
.withHttpStatus(status)
|
|
.withRequest(method, url)
|
|
}
|
|
|
|
const err = newError(
|
|
ErrorCode.Server4xxOther,
|
|
wire.message ?? `request failed (HTTP ${status})`,
|
|
)
|
|
.withHttpStatus(status)
|
|
.withRequest(method, url)
|
|
return wire.hint !== undefined ? err.withHint(wire.hint) : err
|
|
}
|
|
|
|
export function classifyTransportError(err: unknown): BaseError {
|
|
const message = err instanceof Error ? err.message : String(err)
|
|
const sanitized = redactBearer(message)
|
|
|
|
if (err instanceof Error && err.name === 'TimeoutError')
|
|
return newError(ErrorCode.NetworkTimeout, 'request timed out').wrap(err)
|
|
if (err instanceof Error && err.name === 'AbortError')
|
|
return newError(ErrorCode.NetworkTimeout, 'request aborted').wrap(err)
|
|
if (sanitized.toLowerCase().includes('econnrefused'))
|
|
return newError(ErrorCode.NetworkDns, 'connection refused').wrap(err)
|
|
if (sanitized.toLowerCase().includes('enotfound'))
|
|
return newError(ErrorCode.NetworkDns, 'host lookup failed').wrap(err)
|
|
if (sanitized.toLowerCase().includes('etimedout'))
|
|
return newError(ErrorCode.NetworkTimeout, 'connection timed out').wrap(err)
|
|
|
|
return newError(ErrorCode.Unknown, sanitized).wrap(err)
|
|
}
|