Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 1.6 #36

Merged
merged 10 commits into from
Feb 15, 2017
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ node_js:
- "1.8"
- "2.5"
- "3.3"
- "4.6"
- "4.7"
- "5.12"
- "6.9"
- "7.1"
- "7.5"
sudo: false
cache:
directories:
Expand Down
9 changes: 9 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
unreleased
==========

* Accept custom 4xx and 5xx status codes in factory
* Add deprecation message to `"I'mateapot"` export
* Deprecate passing status code as anything except first argument in factory
* Deprecate using non-error status codes
* Make `message` property enumerable for `HttpError`s

2016-11-16 / 1.5.1
==================

Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ All errors inherit from JavaScript `Error` and the exported `createError.HttpErr
- `headers` - can be an object of header names to values to be sent to the
client, defaulting to `undefined`. When defined, the key names should all
be lower-cased
- `message`
- `status` and `statusCode` - the status code of the error, defaulting to `500`
- `message` - the traditional error message, which should be kept short and all
single line
- `status` - the status code of the error, mirroring `statusCode` for general
compatibility
- `statusCode` - the status code of the error, defaulting to `500`

### createError([status], [message], [properties])

Expand Down
55 changes: 46 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* @private
*/

var deprecate = require('depd')('http-errors')
var setPrototypeOf = require('setprototypeof')
var statuses = require('statuses')
var inherits = require('inherits')
Expand All @@ -27,6 +28,15 @@ module.exports.HttpError = createHttpErrorConstructor()
// Populate exports for all constructors
populateConstructorExports(module.exports, statuses.codes, module.exports.HttpError)

/**
* Get the code class of a status code.
* @private
*/

function codeClass (status) {
return Number(String(status).charAt(0) + '00')
}

/**
* Create a new HTTP Error.
*
Expand All @@ -53,19 +63,27 @@ function createError () {
break
case 'number':
status = arg
if (i !== 0) {
deprecate('non-first-argument status code; replace with createError(' + arg + ', ...)')
}
break
case 'object':
props = arg
break
}
}

if (typeof status !== 'number' || !statuses[status]) {
if (typeof status === 'number' && (status < 400 || status >= 600)) {
deprecate('non-error status code; use only 4xx or 5xx status codes')
}

if (typeof status !== 'number' ||
(!statuses[status] && (status < 400 || status >= 600))) {
status = 500
}

// constructor
var HttpError = createError[status]
var HttpError = createError[status] || createError[codeClass(status)]

if (!err) {
// create error
Expand All @@ -75,7 +93,7 @@ function createError () {
Error.captureStackTrace(err, createError)
}

if (!HttpError || !(err instanceof HttpError)) {
if (!HttpError || !(err instanceof HttpError) || err.status !== status) {
// add properties to generic error
err.expose = status < 500
err.status = err.statusCode = status
Expand Down Expand Up @@ -115,14 +133,23 @@ function createClientErrorConstructor (HttpError, name, code) {

function ClientError (message) {
// create the error object
var err = new Error(message != null ? message : statuses[code])
var msg = message != null ? message : statuses[code]
var err = new Error(msg)

// capture a stack trace to the construction point
Error.captureStackTrace(err, ClientError)

// adjust the [[Prototype]]
setPrototypeOf(err, ClientError.prototype)

// redefine the error message
Object.defineProperty(err, 'message', {
enumerable: true,
configurable: true,
value: msg,
writable: true
})

// redefine the error name
Object.defineProperty(err, 'name', {
enumerable: false,
Expand Down Expand Up @@ -153,14 +180,23 @@ function createServerErrorConstructor (HttpError, name, code) {

function ServerError (message) {
// create the error object
var err = new Error(message != null ? message : statuses[code])
var msg = message != null ? message : statuses[code]
var err = new Error(msg)

// capture a stack trace to the construction point
Error.captureStackTrace(err, ServerError)

// adjust the [[Prototype]]
setPrototypeOf(err, ServerError.prototype)

// redefine the error message
Object.defineProperty(err, 'message', {
enumerable: true,
configurable: true,
value: msg,
writable: true
})

// redefine the error name
Object.defineProperty(err, 'name', {
enumerable: false,
Expand Down Expand Up @@ -191,11 +227,11 @@ function populateConstructorExports (exports, codes, HttpError) {
var CodeError
var name = toIdentifier(statuses[code])

switch (String(code).charAt(0)) {
case '4':
switch (codeClass(code)) {
case 400:
CodeError = createClientErrorConstructor(HttpError, name, code)
break
case '5':
case 500:
CodeError = createServerErrorConstructor(HttpError, name, code)
break
}
Expand All @@ -208,7 +244,8 @@ function populateConstructorExports (exports, codes, HttpError) {
})

// backwards-compatibility
exports["I'mateapot"] = exports.ImATeapot
exports["I'mateapot"] = deprecate.function(exports.ImATeapot,
'"I\'mateapot"; use "ImATeapot" instead')
}

/**
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@
"license": "MIT",
"repository": "jshttp/http-errors",
"dependencies": {
"depd": "1.1.0",
"inherits": "2.0.3",
"setprototypeof": "1.0.2",
"statuses": ">= 1.3.1 < 2"
},
"devDependencies": {
"eslint": "3.10.2",
"eslint": "3.15.0",
"eslint-config-standard": "6.2.1",
"eslint-plugin-markdown": "1.0.0-beta.3",
"eslint-plugin-promise": "3.3.2",
Expand Down
19 changes: 19 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@

process.env.NO_DEPRECATION = 'http-errors'

var assert = require('assert')
var util = require('util')

Expand All @@ -20,6 +23,22 @@ describe('HTTP Errors', function () {
assert.equal(err.statusCode, 300)
})

it('create(status) for 471', function () {
var err = create(471)
assert.equal(err.name, 'BadRequestError')
assert.equal(err.message, 'Bad Request')
assert.equal(err.status, 471)
assert.equal(err.statusCode, 471)
})

it('create(status) for 520', function () {
var err = create(520)
assert.equal(err.name, 'InternalServerError')
assert.equal(err.message, 'Internal Server Error')
assert.equal(err.status, 520)
assert.equal(err.statusCode, 520)
})

it('create(status, msg)', function () {
var err = create(404, 'LOL')
assert.equal(err.name, 'NotFoundError')
Expand Down