mirror of
https://github.com/langgenius/dify.git
synced 2026-06-11 10:57:40 +08:00
81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import { BaseError, HttpClientError, 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, raw } = 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 HttpClientError.from(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 HttpClientError.from(newError(
|
|
ErrorCode.Server5xx,
|
|
wire.message ?? `server error (HTTP ${status})`,
|
|
))
|
|
.withHttpStatus(status)
|
|
.withRequest(method, url)
|
|
.withRawResponse(raw)
|
|
}
|
|
|
|
const err = HttpClientError.from(newError(
|
|
ErrorCode.Server4xxOther,
|
|
wire.message ?? `request failed (HTTP ${status})`,
|
|
))
|
|
.withHttpStatus(status)
|
|
.withRequest(method, url)
|
|
.withRawResponse(raw)
|
|
return wire.hint !== undefined ? err.withHint(wire.hint) : err
|
|
}
|
|
|
|
export function classifyTransportError(err: unknown): BaseError {
|
|
if (err instanceof BaseError) {
|
|
return err
|
|
}
|
|
if (!(err instanceof Error)) {
|
|
return newError(ErrorCode.Unknown, String(err)).wrap(err)
|
|
}
|
|
const sanitized = redactBearer(err.message)
|
|
// there isn't a practical way to classify network errors reliably
|
|
return newError(ErrorCode.NetworkConnection, sanitized).wrap(err)
|
|
}
|