developer #4
@ -66,8 +66,35 @@ export default defineEventHandler(async (event) => {
|
|||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
const fetchErr = err as { response?: { status?: number; _data?: unknown } }
|
const fetchErr = err as { response?: { status?: number; _data?: unknown } }
|
||||||
if (fetchErr.response) {
|
if (fetchErr.response) {
|
||||||
setResponseStatus(event, fetchErr.response.status ?? 500)
|
const status = fetchErr.response.status ?? 500
|
||||||
return fetchErr.response._data
|
const raw = fetchErr.response._data
|
||||||
|
|
||||||
|
// responseType: 'stream' faz _data ser ReadableStream mesmo em erros —
|
||||||
|
// lemos o stream e parseamos como JSON para que o cliente veja o envelope de erro
|
||||||
|
let body: unknown = raw
|
||||||
|
if (raw && typeof (raw as ReadableStream).getReader === 'function') {
|
||||||
|
const reader = (raw as ReadableStream<Uint8Array>).getReader()
|
||||||
|
const chunks: Uint8Array[] = []
|
||||||
|
for (;;) {
|
||||||
|
const { value, done } = await reader.read()
|
||||||
|
if (done) break
|
||||||
|
if (value) chunks.push(value)
|
||||||
|
}
|
||||||
|
const totalLen = chunks.reduce((n, c) => n + c.length, 0)
|
||||||
|
const merged = new Uint8Array(totalLen)
|
||||||
|
let offset = 0
|
||||||
|
for (const c of chunks) { merged.set(c, offset); offset += c.length }
|
||||||
|
const text = new TextDecoder().decode(merged)
|
||||||
|
try { body = JSON.parse(text) } catch { body = text }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (import.meta.dev) {
|
||||||
|
console.error(`[proxy] ERRO ${status} ← ${url}`, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
setResponseStatus(event, status)
|
||||||
|
setResponseHeader(event, 'content-type', 'application/json; charset=utf-8')
|
||||||
|
return body
|
||||||
}
|
}
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ export function useApi() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function request<T>(path: string, options: FetchOptions = {}): Promise<T> {
|
async function request<T>(path: string, options: FetchOptions = {}): Promise<T> {
|
||||||
|
try {
|
||||||
return await $fetch<T>(buildUrl(path), {
|
return await $fetch<T>(buildUrl(path), {
|
||||||
...options,
|
...options,
|
||||||
headers: {
|
headers: {
|
||||||
@ -25,6 +26,13 @@ export function useApi() {
|
|||||||
...(options.headers ?? {}),
|
...(options.headers ?? {}),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
} catch (err: unknown) {
|
||||||
|
if (import.meta.dev) {
|
||||||
|
const e = err as { status?: number; data?: unknown }
|
||||||
|
console.error(`[api] ${(options.method ?? 'GET').toUpperCase()} ${path} → ${e.status}`, e.data)
|
||||||
|
}
|
||||||
|
throw err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user