Format error responses properly, return the response body.

    This function can be attached to the Bottle instance as the
    default_error_handler function. It is also used by the
    FormatExceptionMiddleware.

def httperror_handler(error):
    """Format error responses properly, return the response body.

    This function can be attached to the Bottle instance as the
    default_error_handler function. It is also used by the
    FormatExceptionMiddleware.
    """
    status_code = error.status_code or 500
    output = {
        'code': status_code,
        'message': error.body or UNEXPECTED_ERROR,
        'reason': bottle.HTTP_CODES.get(status_code) or None,
    }
    if bottle.DEBUG:
        LOG.warning("Debug-mode server is returning traceback and error "
                    "details in the response with a %s status.",
                    error.status_code)
        if error.exception:
            output['exception'] = repr(error.exception)
        else:
            if any(sys.exc_info()):
                output['exception'] = repr(sys.exc_info()[1])
            else:
                output['exception'] = None

        if error.traceback:
            output['traceback'] = error.traceback
        else:
            if any(sys.exc_info()):
                # Otherwise, format_exc() returns "None\n"
                # which is pretty silly.
                output['traceback'] = traceback.format_exc()
            else:
                output['traceback'] = None

    # overwrite previous body attr with json
    if isinstance(output['message'], bytes):
        output['message'] = output['message'].decode(
            'utf-8', errors='replace')

    # Default type and writer to json.
    accept = bottle.request.get_header('accept') or 'application/json'
    writer = functools.partial(
        json.dumps, sort_keys=True, indent=4)
    error.set_header('Content-Type', 'application/json')
    if 'json' not in accept:
        if 'yaml' in accept:
            if not yaml:
                LOG.warning("Yaml requested but pyyaml is not installed.")
            else:
                error.set_header('Content-Type', 'application/x-yaml')
                writer = functools.partial(
                    yaml.safe_dump,
                    default_flow_style=False,
                    indent=4)
            # html could be added here.

    error.body = [writer(output).encode('utf8')]
    return error.body