/**
* Intercept writes for head requests, do not send to client,
* but send length, and make body available in context.
+ * N.B. If persisted, ctx.responseBody will be a raw buffer, be aware when logging.
* @param {http.ClientRequest} req
* @param {http.ServerResponse} res
* @param {object} ctx
+ * @param {Boolean} persistResponseBody
*/
- static setHeadHandler(req, res, ctx) {
+ static setHeadHandler(req, res, ctx, persistResponseBody = false) {
if (req.method === 'HEAD') {
const origEnd = res.end.bind(res);
const chunks = [];
};
res.end = function (data, encoding, ...rest) {
Dingus.pushBufChunk(chunks, data, encoding);
- ctx.responseBody = Buffer.concat(chunks);
- res.setHeader(Enum.Header.ContentLength, Buffer.byteLength(ctx.responseBody));
+ const responseBody = Buffer.concat(chunks);
+ res.setHeader(Enum.Header.ContentLength, Buffer.byteLength(responseBody));
+ if (persistResponseBody) {
+ ctx.responseBody = responseBody;
+ }
return origEnd(undefined, encoding, ...rest);
};
}
/**
- * Parse rawBody from ctx as contentType into parsedBody.
- * @param {string} contentType
- * @param {object} ctx
- */
- parseBody(contentType, ctx) {
+ * Parse rawBody as contentType into ctx.parsedBody.
+ * @param {string} contentType
+ * @param {object} ctx
+ * @param {string|buffer}
+ */
+ parseBody(contentType, ctx, rawBody) {
const _scope = _fileScope('parseBody');
+ if (!rawBody) {
+ // 1.2.4 and earlier expected rawBody on context
+ rawBody = ctx.rawBody;
+ }
+
switch (contentType) {
case Enum.ContentType.ApplicationForm:
- ctx.parsedBody = this.querystring.parse(ctx.rawBody);
+ ctx.parsedBody = this.querystring.parse(rawBody);
break;
case Enum.ContentType.ApplicationJson:
try {
- ctx.parsedBody = JSON.parse(ctx.rawBody);
+ ctx.parsedBody = JSON.parse(rawBody);
} catch (e) {
this.logger.debug(_scope, 'JSON parse failed', { requestId: ctx.requestId, error: e });
throw new ResponseError(Enum.ErrorResponse.BadRequest, e.message);
* @param {http.ClientRequest} req
* @param {http.ServerResponse} res
* @param {object} ctx
- */
- async ingestBody(req, res, ctx) {
- ctx.rawBody = await this.bodyData(req);
- const contentType = Dingus.getRequestContentType(req);
- this.parseBody(contentType, ctx);
+ * @param {object}
+ * @param {Boolean} .parseEmptyBody
+ * @param {Boolean} .persistRawBody
+ */
+ async ingestBody(req, res, ctx, { parseEmptyBody = true, persistRawBody = false, maximumBodySize } = {}) {
+ const rawBody = await this.bodyData(req, maximumBodySize);
+ if (persistRawBody) {
+ ctx.rawBody = rawBody;
+ }
+ if (rawBody || parseEmptyBody) {
+ const contentType = Dingus.getRequestContentType(req);
+ this.parseBody(contentType, ctx, rawBody);
+ }
}