You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
2.4 KiB

import ResponseFactory from './ResponseFactory.ts'
import {Request} from '../Request.ts'
import * as api from '../../support/api.ts'
import {HTTPStatus} from '../../const/http.ts'
/**
* Response factory to render a handled request-level error.
* @extends ResponseFactory
*/
export default class ErrorResponseFactory extends ResponseFactory {
/**
* The target output mode.
* @type 'json' | 'html'
*/
protected target_mode: 'json' | 'html' = 'html'
constructor(
/**
* The error to display.
* @type Error
*/
public readonly error: Error,
/**
* THe HTTP status to use for the response.
* @type HTTPStatus
*/
status: HTTPStatus = HTTPStatus.INTERNAL_SERVER_ERROR,
/**
* The output format.
* @type 'json' | 'html'
*/
output: 'json' | 'html' = 'html',
) {
super()
this.status(status)
this.mode(output)
}
/**
* Override the output mode.
* @param {'json' | 'html'} output
* @return ErrorResponseFactory
*/
public mode(output: 'json' | 'html'): ErrorResponseFactory {
this.target_mode = output
return this
}
/**
* Write this response factory to the given request's response.
* @param {Request} request
* @return Request
*/
public async write(request: Request): Promise<Request> {
request = await super.write(request)
if ( this.target_mode === 'json' ) {
request.response.headers.set('Content-Type', 'application/json')
request.response.body = this.build_json(this.error)
} else if ( this.target_mode === 'html' ) {
request.response.headers.set('Content-Type', 'text/html')
request.response.body = this.build_html(this.error)
}
return request
}
/**
* Build the HTML display for the given error.
* @param {Error} error
* @return string
*/
protected build_html(error: Error) {
return `
<b>Sorry, an unexpected error occurred while processing your request.</b>
<br>
<pre><code>
Name: ${error.name}
Message: ${error.message}
Stack trace:
- ${error.stack ? error.stack.split(/\s+at\s+/).slice(1).join('<br> - ') : 'none'}
</code></pre>
`
}
protected build_json(error: Error) {
return JSON.stringify(api.error(error))
}
}