<commit_before>'use strict';


const { chain } = require('lodash');

const { ErrorHandlerError } = require('../../error');
const { log, isDev } = require('../../utilities');
const { getErrorInfo } = require('./reasons');
const protocolErrorHandlers = require('./protocol');
const interfaceErrorHandlers = require('./interface');


/**
 * Sends error back to client
 *
 * @param {object} options
 * @param {Error} options.exception
 * @param {object} options.input - protocol-independent request/response object
 * @param {string} options.protocol - e.g. 'http'
 */
const sendError = ({ onRequestError = () => {} }) => {
  return function sendErrorFunc({
    exception,
    input = {},
    info = {},
    retry = false,
  }) {
    const { protocol, interface: interf } = info;
    try {
      const protocolErrorHandler = protocolErrorHandlers[protocol];
      const interfaceErrorHandler = interfaceErrorHandlers[interf];

      // Retrieves protocol-independent error information, using the thrown exception
      const genericErrorInput = getErrorInfo({ exception });
      let response = createResponse({ exception, errorInput: genericErrorInput });

      // Adds protocol-specific error information
      const protocolErrorInput = Object.assign({}, input, info, getErrorInfo({ exception, protocol }));
      response = protocolErrorHandler.processResponse({ response, errorInput: protocolErrorInput });

      // Adds interface-specific error information
      if (interfaceErrorHandler) {
        response = interfaceErrorHandler.processResponse({ response });
      }

      response = sortResponseKeys({ response });

      // Use protocol-specific way to send back the response
      protocolErrorHandler.sendResponse({ response, input });
      log.error(response.error);
      onRequestError(response.error);
    // Retries once if it fails
    } catch (innererror) {
      const errorHandlerError = new ErrorHandlerError('Error handler failed', { reason: 'ERROR_HANDLER_FAILURE', innererror });
      log.error(errorHandlerError);
      onRequestError(errorHandlerError);
      if (retry) { return; }
      sendErrorFunc({ exception: innererror, input, info: { protocol }, retry: true });
    }
  };
};

// Creates protocol-independent response error
const createResponse = function ({ exception, errorInput }) {
  const message = typeof exception === 'string' ? exception : exception.message;

  const response = {
    error: {
      type: exception.reason,
      title: errorInput.title,
      // Long description
      description: message || errorInput.description,
    },
    // See RFC 7807
    contentType: 'application/problem+json',
  };

  // Not in production
  if (isDev()) {
    Object.assign(response.error, {
      // Recrursive stack trace
      details: (exception.innererror && exception.innererror.stack) || exception.stack,
    });
  }

  // Any custom information
  Object.assign(response.error, exception.extra);

  return response;
};

const sortedKeys = ['status', 'type', 'title', 'description', 'instance', 'details'];
const sortResponseKeys = function ({ response }) {
  response.error = chain(response.error)
    .toPairs()
    .sortBy(([key]) => {
      let index = sortedKeys.indexOf(key);
      if (index === -1) {
        index = sortedKeys.length;
      }
      return index;
    })
    .fromPairs()
    .value();
  return response;
};


module.exports = {
  sendError,
};
<commit_msg>Fix line width<commit_after>'use strict';


const { chain } = require('lodash');

const { ErrorHandlerError } = require('../../error');
const { log, isDev } = require('../../utilities');
const { getErrorInfo } = require('./reasons');
const protocolErrorHandlers = require('./protocol');
const interfaceErrorHandlers = require('./interface');


/**
 * Sends error back to client
 *
 * @param {object} options
 * @param {Error} options.exception
 * @param {object} options.input - protocol-independent request/response object
 * @param {string} options.protocol - e.g. 'http'
 */
const sendError = ({ onRequestError = () => {} }) => {
  return function sendErrorFunc({
    exception,
    input = {},
    info = {},
    retry = false,
  }) {
    const { protocol, interface: interf } = info;
    try {
      const protocolErrorHandler = protocolErrorHandlers[protocol];
      const interfaceErrorHandler = interfaceErrorHandlers[interf];

      // Retrieves protocol-independent error information,
      // using the thrown exception
      const genericErrorInput = getErrorInfo({ exception });
      let response = createResponse({
        exception,
        errorInput: genericErrorInput,
      });

      // Adds protocol-specific error information
      const errorInfo = getErrorInfo({ exception, protocol });
      const protocolErrorInput = Object.assign({}, input, info, errorInfo);
      response = protocolErrorHandler.processResponse({
        response,
        errorInput: protocolErrorInput,
      });

      // Adds interface-specific error information
      if (interfaceErrorHandler) {
        response = interfaceErrorHandler.processResponse({ response });
      }

      response = sortResponseKeys({ response });

      // Use protocol-specific way to send back the response
      protocolErrorHandler.sendResponse({ response, input });
      log.error(response.error);
      onRequestError(response.error);
    // Retries once if it fails
    } catch (innererror) {
      const errorHandlerError = new ErrorHandlerError('Error handler failed', {
        reason: 'ERROR_HANDLER_FAILURE',
        innererror,
      });
      log.error(errorHandlerError);
      onRequestError(errorHandlerError);
      if (retry) { return; }
      sendErrorFunc({
        exception: innererror,
        input,
        info: { protocol },
        retry: true,
      });
    }
  };
};

// Creates protocol-independent response error
const createResponse = function ({ exception, errorInput }) {
  const message = typeof exception === 'string' ? exception : exception.message;

  const response = {
    error: {
      type: exception.reason,
      title: errorInput.title,
      // Long description
      description: message || errorInput.description,
    },
    // See RFC 7807
    contentType: 'application/problem+json',
  };

  // Not in production
  if (isDev()) {
    // Recrursive stack trace
    const details = (exception.innererror && exception.innererror.stack) ||
      exception.stack;
    Object.assign(response.error, { details });
  }

  // Any custom information
  Object.assign(response.error, exception.extra);

  return response;
};

const sortedKeys = [
  'status',
  'type',
  'title',
  'description',
  'instance',
  'details',
];
const sortResponseKeys = function ({ response }) {
  response.error = chain(response.error)
    .toPairs()
    .sortBy(([key]) => {
      let index = sortedKeys.indexOf(key);
      if (index === -1) {
        index = sortedKeys.length;
      }
      return index;
    })
    .fromPairs()
    .value();
  return response;
};


module.exports = {
  sendError,
};

{'fraction_non_alphanumeric': 0.12963225898054806, 'fraction_numerical': 0.0014198494959534289, 'mean_word_length': 3.0977312390924956, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2964723', 'n_tokens_mistral': 1886, 'n_tokens_neox': 1874, 'n_words': 487}