Source: response.js

/**
 * Response Q4S module. Implements the Response Q4S class that implements
 * response logic and manipulation.
 * @module ResQ4S
 * @license Apache-2.0
 */

const Util = require('./util');

/**
 * An enumerator which defines the reason phrase for each of the error
 * codes that a response may contain.
 */
const REASON_PHRASES = Object.freeze({
  100: 'Trying',
  200: 'Ok',
  400: 'Bad Request',
  404: 'Not Found',
  405: 'Method Not Allowed',
  406: 'Not Acceptable',
  408: 'Request Timeout',
  413: 'Request Entity Too Large',
  414: 'Request-URI Too Long',
  415: 'Unsoported Media Type',
  416: 'Unsoported URI Scheme',
  500: 'Server Internal Error',
  501: 'Not Implemented',
  503: 'Service Unavailable',
  504: 'Server Time-out',
  505: 'Version Not Supported',
  513: 'Message Too Large',
  600: 'Session Does Not Exist',
  601: 'Quality Level Not Allowed',
  603: 'Session not Allowed',
  604: 'Authorization Nor Allowed',
});

/**
 * Response Q4S class. Options to build , generate, parse and validate Q4S
 * responses
 */
class ResQ4S {
  /**
   * Constructor for the ReqQ4S class. Does not validate input data coherence.
   * @param {string} q4sVersion - The string containing the Q4S version.
   * @param {number} statusCode - The status code of the response
   * @param {string} reasonPhrase - The reason of the response
   * @param {Object} headers - Object containing all the headers.
   * @param {string} headers.headername - One entry in the object for each
   * header.
   * @param {string} body - The body of the request. Normally a sdp message.
   */
  constructor(q4sVersion, statusCode, reasonPhrase, headers, body) {
    /**
     * The Q4S protocol version
     * @member {String}
     * */
    this.q4sVersion = q4sVersion;
    /**
     * The status code
     * @member {Number}
     * */
    this.statusCode = statusCode;
    /**
     * String containing a human redable reasoning of the error code.
     * @member {String}
     * */
    this.reasonPhrase = reasonPhrase;
    /**
     * Object containing the headers. Each property name os the name of the
     * header. Its value is the field.
     * @member {Object}
     */
    this.headers = headers;
    /**
     * The body of the response.
     * @member {String}
     */
    this.body = body;
  }
  /**
   * Factory method to build a new ResQ4S abstracting part of the details.
   * @param {number} statusCode - The status code of the response
   * @param {Object} headers - Object containing all the headers.
   * @param {string} headers.headername - One entry in the object for each
   * header.
   * @param {string} body - The body of the request. Normally a sdp message.
   * returns an error.
   * @return {ResQ4SQ}
   */
  static genRes(statusCode, headers, body) {
    return new ResQ4S(
        Util.Q4SVERSION,
        statusCode,
        REASON_PHRASES[statusCode],
        headers,
        body);
  }
  /**
   * Factory method to build a new ResQ4S from an string. Validates the the
   * string is correct.
   * @param {string} str - The string to parse to the ReqQ4S.
   * @return {Object} On sucess an object of the class ResQ4S, on error
   * returns an error.
   */
  static fromString(str) {
    let q4sVersion; let statusCode; let reasonPhrase;
    const headers = {};
    const body = str.substring(str.indexOf('\r\n\r\n') + 4);
    const headerPart = str.substring(0, str.indexOf('\r\n\r\n'));
    const headLine = headerPart.split('\r\n');
    headLine.forEach((item, index) => {
      if (index === 0) {
        const values = item.split(' ');
        q4sVersion = values[0];
        statusCode = parseInt(values[1], 10);
        reasonPhrase = values[2];
      } else {
        const header = item.split(': ');
        headers[header[0]] = header[1];
      }
    });
    const res = new ResQ4S(q4sVersion, statusCode, reasonPhrase, headers,
        body);
    res.validate();
    return res;
  }

  /**
   * Check that the data is correct and follows the required rules. This
   * method checks the response, so there wont be body validation.
   * @return {boolean} True is the data is correct. False otherwise.
   */
  validate() { // TODO: Improve this comprobation when you have the class clear
    // TODO -> Content-Type debe de estar en todas las request que se manden
    // TODO -> "Accept-Encoding" header debe de ser "identity" forzado
    // TODO -> Si es chunqued me lo cargo
    return true;
  }

  /**
   * Form the message format of this Response and send it over the network.
   * @return {string} -  String format of this Request.
   */
  toString() {
    let message = '';

    message = message + this.q4sVersion + ' ' + this.statusCode + ' ';
    message = message + this.reasonPhrase + '\r\n';

    if (this.headers) {
      const entries = Object.entries(this.headers);
      entries.forEach((item) => {
        message = message + item[0] + ': ' + item[1] + '\r\n';
      });
    }
    message = message + '\r\n';
    if (this.body) {
      message = message + this.body;
    }
    return message;
  }
};

module.exports = ResQ4S;