2025-04-02 06:50:39 -04:00

105 lines
2.4 KiB
JavaScript

'use strict';
const assert = require('node:assert');
const { ResponseStatusCodeError } = require('../core/errors');
const { chunksDecode } = require('./readable');
const CHUNK_LIMIT = 128 * 1024;
async function getResolveErrorBodyCallback({
callback,
body,
contentType,
statusCode,
statusMessage,
headers,
}) {
assert(body);
let chunks = [];
let length = 0;
try {
for await (const chunk of body) {
chunks.push(chunk);
length += chunk.length;
if (length > CHUNK_LIMIT) {
chunks = [];
length = 0;
break;
}
}
} catch {
chunks = [];
length = 0;
// Do nothing....
}
const message = `Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`;
if (statusCode === 204 || !contentType || !length) {
queueMicrotask(() =>
callback(new ResponseStatusCodeError(message, statusCode, headers))
);
return;
}
const stackTraceLimit = Error.stackTraceLimit;
Error.stackTraceLimit = 0;
let payload;
try {
if (isContentTypeApplicationJson(contentType)) {
payload = JSON.parse(chunksDecode(chunks, length));
} else if (isContentTypeText(contentType)) {
payload = chunksDecode(chunks, length);
}
} catch {
// process in a callback to avoid throwing in the microtask queue
} finally {
Error.stackTraceLimit = stackTraceLimit;
}
queueMicrotask(() =>
callback(new ResponseStatusCodeError(message, statusCode, headers, payload))
);
}
const isContentTypeApplicationJson = (contentType) => {
return (
contentType.length > 15 &&
contentType[11] === '/' &&
contentType[0] === 'a' &&
contentType[1] === 'p' &&
contentType[2] === 'p' &&
contentType[3] === 'l' &&
contentType[4] === 'i' &&
contentType[5] === 'c' &&
contentType[6] === 'a' &&
contentType[7] === 't' &&
contentType[8] === 'i' &&
contentType[9] === 'o' &&
contentType[10] === 'n' &&
contentType[12] === 'j' &&
contentType[13] === 's' &&
contentType[14] === 'o' &&
contentType[15] === 'n'
);
};
const isContentTypeText = (contentType) => {
return (
contentType.length > 4 &&
contentType[4] === '/' &&
contentType[0] === 't' &&
contentType[1] === 'e' &&
contentType[2] === 'x' &&
contentType[3] === 't'
);
};
module.exports = {
getResolveErrorBodyCallback,
isContentTypeApplicationJson,
isContentTypeText,
};