event_request
Version:
A Backend Server
106 lines (90 loc) • 2.68 kB
JavaScript
;
// Dependencies
const { EventEmitter } = require( 'events' );
/**
* @brief Constants
*/
const JSON_BODY_PARSER_SUPPORTED_TYPE = 'application/json';
const CONTENT_LENGTH_HEADER = 'content-length';
const CONTENT_TYPE_HEADER = 'content-type';
/**
* @brief JsonBodyParser responsible for parsing application/json forms
*/
class JsonBodyParser extends EventEmitter {
/**
* @param {Object} [options={}]
* @param {Number} options.maxPayloadLength - The max size of the body to be parsed
* @param {Boolean} options.strict - Whether the received payload must match the content-length
*/
constructor( options = {} ) {
super();
this.setMaxListeners( 0 );
// Defaults to 100 MB
this.maxPayloadLength = typeof options.maxPayloadLength === 'number'
? options.maxPayloadLength
: 104857600;
this.strict = typeof options.strict === 'boolean'
? options.strict
: false;
}
/**
* @brief Returns a boolean if the current body parser supports the request
*
* @param {EventRequest} event
*
* @return {Boolean}
*/
supports( event ) {
const contentType = event.getRequestHeader( CONTENT_TYPE_HEADER );
return typeof contentType === 'string' && contentType.match( JSON_BODY_PARSER_SUPPORTED_TYPE ) !== null;
}
/**
* @brief Parses the request
*
* @async
* @param {EventRequest} event
*
* @return {Promise<Object>}
*/
parse( event ) {
return new Promise(( resolve, reject ) => {
let rawBody = [];
let payloadLength = 0;
if ( ! this.supports( event ) )
return reject( { code: 'app.er.bodyParser.json.notSupported' } );
event.request.on( 'data', ( data ) => {
if ( ! event.isFinished() ) {
payloadLength += data.length;
if ( payloadLength <= this.maxPayloadLength )
rawBody.push( data );
}
});
event.request.on( 'end', () => {
if ( ! event.isFinished() ) {
rawBody = Buffer.concat( rawBody, payloadLength );
if ( payloadLength > this.maxPayloadLength || payloadLength === 0 )
return resolve( { body: {}, rawBody: {} } );
if (
this.strict &&
(
typeof event.headers !== 'object'
|| typeof event.headers[CONTENT_LENGTH_HEADER] === 'undefined'
|| payloadLength !== Number( event.headers[CONTENT_LENGTH_HEADER] )
)
) {
return resolve( { body: {}, rawBody: {} } );
}
try {
rawBody = rawBody.toString();
const body = JSON.parse( rawBody );
resolve( { body, rawBody } );
}
catch ( error ) {
reject( { code: 'app.er.bodyParser.json.errorParsing' } );
}
}
});
});
}
}
module.exports = JsonBodyParser;