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

104 lines
2.4 KiB
JavaScript

'use strict';
// const { parseHeaders } = require('../core/util')
const DecoratorHandler = require('../handler/decorator-handler');
const { ResponseError } = require('../core/errors');
class ResponseErrorHandler extends DecoratorHandler {
#statusCode;
#contentType;
#decoder;
#headers;
#body;
constructor(_opts, { handler }) {
super(handler);
}
#checkContentType(contentType) {
return (this.#contentType ?? '').indexOf(contentType) === 0;
}
onRequestStart(controller, context) {
this.#statusCode = 0;
this.#contentType = null;
this.#decoder = null;
this.#headers = null;
this.#body = '';
return super.onRequestStart(controller, context);
}
onResponseStart(controller, statusCode, headers, statusMessage) {
this.#statusCode = statusCode;
this.#headers = headers;
this.#contentType = headers['content-type'];
if (this.#statusCode < 400) {
return super.onResponseStart(
controller,
statusCode,
headers,
statusMessage
);
}
if (
this.#checkContentType('application/json') ||
this.#checkContentType('text/plain')
) {
this.#decoder = new TextDecoder('utf-8');
}
}
onResponseData(controller, chunk) {
if (this.#statusCode < 400) {
return super.onResponseData(controller, chunk);
}
this.#body += this.#decoder?.decode(chunk, { stream: true }) ?? '';
}
onResponseEnd(controller, trailers) {
if (this.#statusCode >= 400) {
this.#body += this.#decoder?.decode(undefined, { stream: false }) ?? '';
if (this.#checkContentType('application/json')) {
try {
this.#body = JSON.parse(this.#body);
} catch {
// Do nothing...
}
}
let err;
const stackTraceLimit = Error.stackTraceLimit;
Error.stackTraceLimit = 0;
try {
err = new ResponseError('Response Error', this.#statusCode, {
body: this.#body,
headers: this.#headers,
});
} finally {
Error.stackTraceLimit = stackTraceLimit;
}
super.onResponseError(controller, err);
} else {
super.onResponseEnd(controller, trailers);
}
}
onResponseError(controller, err) {
super.onResponseError(controller, err);
}
}
module.exports = () => {
return (dispatch) => {
return function Intercept(opts, handler) {
return dispatch(opts, new ResponseErrorHandler(opts, { handler }));
};
};
};