|
|
import { sendProxyError } from "../common"; |
|
|
import type { RawResponseBodyHandler } from "./index"; |
|
|
import { decompressBuffer } from "./compression"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const handleBlockingResponse: RawResponseBodyHandler = async ( |
|
|
proxyRes, |
|
|
req, |
|
|
res |
|
|
) => { |
|
|
if (req.isStreaming) { |
|
|
const err = new Error( |
|
|
"handleBlockingResponse called for a streaming request." |
|
|
); |
|
|
req.log.error({ stack: err.stack, api: req.inboundApi }, err.message); |
|
|
throw err; |
|
|
} |
|
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
let chunks: Buffer[] = []; |
|
|
proxyRes.on("data", (chunk) => chunks.push(chunk)); |
|
|
proxyRes.on("end", async () => { |
|
|
const contentEncoding = proxyRes.headers["content-encoding"]; |
|
|
const contentType = proxyRes.headers["content-type"]; |
|
|
let body: string | Buffer = Buffer.concat(chunks); |
|
|
const rejectWithMessage = function (msg: string, err: Error) { |
|
|
const error = `${msg} (${err.message})`; |
|
|
req.log.warn( |
|
|
{ msg: error, stack: err.stack }, |
|
|
"Error in blocking response handler" |
|
|
); |
|
|
sendProxyError(req, res, 500, "Internal Server Error", { error }); |
|
|
return reject(error); |
|
|
}; |
|
|
|
|
|
try { |
|
|
body = await decompressBuffer(body, contentEncoding); |
|
|
} catch (e) { |
|
|
return rejectWithMessage(`Could not decode response body`, e); |
|
|
} |
|
|
|
|
|
try { |
|
|
return resolve(tryParseAsJson(body, contentType)); |
|
|
} catch (e) { |
|
|
return rejectWithMessage("API responded with invalid JSON", e); |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
|
|
|
function tryParseAsJson(body: string, contentType?: string) { |
|
|
|
|
|
if (contentType?.includes("application/json")) { |
|
|
return JSON.parse(body); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
return JSON.parse(body); |
|
|
} catch (e) { |
|
|
return body; |
|
|
} |
|
|
} |
|
|
|