UNPKG

api-problem

Version:
94 lines (73 loc) 2.19 kB
const STATUS_CODES = require('http').STATUS_CODES const BASE_URI = '' const CONTENT_TYPE = 'application/problem+json' const DEFAULT_TYPE = 'about:blank' const ERR_STATUS = '"status" must be a valid HTTP Error Status Code ([RFC7231], Section 6)' const ERR_TITLE = 'missing "title". a short, human-readable summary of the problem type' const STATUS_CODES_WEB = 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/' // polyfill require('./polyfill') module.exports = class Problem extends Error { constructor () { const args = Array.from(arguments) const status = args.shift() let base = Problem.BASE_URI || BASE_URI let members let title let type let i = 3 while (i--) { if (typeof args[i] === 'object') { members = args.pop() title = args.shift() type = args.pop() } } if (args.length) { title = args.shift() type = args.shift() } if (!type) { type = Problem.DEFAULT_TYPE || DEFAULT_TYPE } if (!status) { throw new Error(ERR_STATUS) } const statusNumber = Number(status) if ((statusNumber >= 600 || statusNumber < 400) && statusNumber !== 207) { throw new Error(ERR_STATUS) } if (!title && STATUS_CODES.hasOwnProperty(status)) { title = STATUS_CODES[status] } if (type === DEFAULT_TYPE) { type = STATUS_CODES_WEB + status // reset base_uri base = '' } if (!title) { throw new Error(ERR_TITLE) } super(`[${String(status)}] ${String(title)} (${base + String(type)})`) this.type = base + String(type) this.title = String(title) this.status = Number(status) if (members && members.instance) { members.instance = base + members.instance } if (members) { Object.assign(this, members) } } toString () { return `[${this.status}] ${this.title} (${this.type})` } toObject () { // escape the Error class return Object.fromEntries(new Map(Object.entries(this))) } send (response, space) { response.writeHead(this.status, { 'Content-Type': CONTENT_TYPE }) response.end(JSON.stringify(this, null, space)) } }