<commit_before>/*
 * @adonisjs/core
 *
 * (c) <NAME> <<EMAIL>>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

import { LoggerContract } from '@ioc:Adonis/Core/Logger'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

/**
 * Http exception handler serves as the base exception handler
 * to handle all exceptions occured during the HTTP request
 * lifecycle and makes appropriate response for them.
 */
export abstract class HttpExceptionHandler {
  /**
   * An array of error codes that must not be reported
   */
  protected dontReport: string[] = []

  /**
   * An array of http statuses that must not be reported. The first
   * level of filteration is on the basis of statuses and then
   * the error codes.
   */
  protected ignoreStatuses: number[] = []

  /**
   * An array of internal error codes to ignore
   * from the reporting list
   */
  protected internalDontReport: string[] = [
    'E_ROUTE_NOT_FOUND',
  ]

  constructor (protected logger: LoggerContract) {
  }

  /**
   * A custom context to send to the logger when reporting
   * errors.
   */
  protected context (ctx: HttpContextContract): any {
    return {
      'x-request-id': ctx.request.id(),
    }
  }

  /**
   * Returns a boolean telling if a given error is supposed
   * to be logged or not
   */
  protected shouldReport (error: any): boolean {
    /**
     * Do not report the error when it's status is mentioned inside
     * the `ignoreStatuses` array.
     */
    if (error.status && this.ignoreStatuses.indexOf(error.status) > -1) {
      return false
    }

    /**
     * Don't report when error has a code and it's in the ignore list.
     */
    if (error.code && this.dontReport.concat(this.internalDontReport).indexOf(error.code) > -1) {
      return false
    }

    return true
  }

  /**
   * Makes the JSON response, based upon the environment in
   * which the app is runing
   */
  protected async makeJSONResponse (error: any, ctx: HttpContextContract) {
    if (process.env.NODE_ENV === 'development') {
      ctx.response.status(error.status).send({
        message: error.message,
        stack: error.stack,
        code: error.code,
      })
      return
    }

    ctx.response.status(error.status).send({
      message: error.message,
    })
  }

  /**
   * Makes the HTML response, based upon the environment in
   * which the app is runing
   */
  protected async makeHtmlResponse (error: any, ctx: HttpContextContract) {
    if (process.env.NODE_ENV === 'development') {
      const Youch = require('youch')
      const html = await new Youch(error, ctx.request.request).toHTML()
      ctx.response.status(error.status).send(html)
      return
    }

    ctx.response.status(error.status).send(`<h1> ${error.message} </h1>`)
  }

  /**
   * Report a given error
   */
  public report (error: any, ctx: HttpContextContract) {
    if (!this.shouldReport(error)) {
      return
    }

    if (typeof (error.report) === 'function') {
      error.report(error, ctx)
      return
    }

    this.logger.error(this.context(ctx), error.message)
  }

  /**
   * Handle exception and make response
   */
  public async handle (error: any, ctx: HttpContextContract) {
    error.status = error.status || 500

    if (typeof (error.handle) === 'function') {
      return error.handle(error, ctx)
    }

    if (ctx.request.accepts(['json'])) {
      return this.makeJSONResponse(error, ctx)
    }

    return this.makeHtmlResponse(error, ctx)
  }
}
<commit_msg>fix(httpExceptionHandler): do content negotiation with html,json both<commit_after>/*
 * @adonisjs/core
 *
 * (c) <NAME> <<EMAIL>>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

import { LoggerContract } from '@ioc:Adonis/Core/Logger'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

/**
 * Http exception handler serves as the base exception handler
 * to handle all exceptions occured during the HTTP request
 * lifecycle and makes appropriate response for them.
 */
export abstract class HttpExceptionHandler {
  /**
   * An array of error codes that must not be reported
   */
  protected dontReport: string[] = []

  /**
   * An array of http statuses that must not be reported. The first
   * level of filteration is on the basis of statuses and then
   * the error codes.
   */
  protected ignoreStatuses: number[] = []

  /**
   * An array of internal error codes to ignore
   * from the reporting list
   */
  protected internalDontReport: string[] = [
    'E_ROUTE_NOT_FOUND',
  ]

  constructor (protected logger: LoggerContract) {
  }

  /**
   * A custom context to send to the logger when reporting
   * errors.
   */
  protected context (ctx: HttpContextContract): any {
    return {
      'x-request-id': ctx.request.id(),
    }
  }

  /**
   * Returns a boolean telling if a given error is supposed
   * to be logged or not
   */
  protected shouldReport (error: any): boolean {
    /**
     * Do not report the error when it's status is mentioned inside
     * the `ignoreStatuses` array.
     */
    if (error.status && this.ignoreStatuses.indexOf(error.status) > -1) {
      return false
    }

    /**
     * Don't report when error has a code and it's in the ignore list.
     */
    if (error.code && this.dontReport.concat(this.internalDontReport).indexOf(error.code) > -1) {
      return false
    }

    return true
  }

  /**
   * Makes the JSON response, based upon the environment in
   * which the app is runing
   */
  protected async makeJSONResponse (error: any, ctx: HttpContextContract) {
    if (process.env.NODE_ENV === 'development') {
      ctx.response.status(error.status).send({
        message: error.message,
        stack: error.stack,
        code: error.code,
      })
      return
    }

    ctx.response.status(error.status).send({
      message: error.message,
    })
  }

  /**
   * Makes the HTML response, based upon the environment in
   * which the app is runing
   */
  protected async makeHtmlResponse (error: any, ctx: HttpContextContract) {
    if (process.env.NODE_ENV === 'development') {
      const Youch = require('youch')
      const html = await new Youch(error, ctx.request.request).toHTML()
      ctx.response.status(error.status).send(html)
      return
    }

    ctx.response.status(error.status).send(`<h1> ${error.message} </h1>`)
  }

  /**
   * Report a given error
   */
  public report (error: any, ctx: HttpContextContract) {
    if (!this.shouldReport(error)) {
      return
    }

    if (typeof (error.report) === 'function') {
      error.report(error, ctx)
      return
    }

    this.logger.error(this.context(ctx), error.message)
  }

  /**
   * Handle exception and make response
   */
  public async handle (error: any, ctx: HttpContextContract) {
    error.status = error.status || 500

    if (typeof (error.handle) === 'function') {
      return error.handle(error, ctx)
    }

    if (ctx.request.accepts(['html', 'json']) === 'json') {
      return this.makeJSONResponse(error, ctx)
    }

    return this.makeHtmlResponse(error, ctx)
  }
}

{'fraction_non_alphanumeric': 0.11738587484390177, 'fraction_numerical': 0.001942555848480644, 'mean_word_length': 2.754166666666667, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, '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': '1863205', 'n_tokens_mistral': 2163, 'n_tokens_neox': 2110, 'n_words': 664}