'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 })) } } }