Skip to content

Instantly share code, notes, and snippets.

@joyrexus
Forked from moleike/http-errors.js
Created June 6, 2016 23:30
Show Gist options
  • Select an option

  • Save joyrexus/cb059ad8e54c3d7ad81a445b1f62f901 to your computer and use it in GitHub Desktop.

Select an option

Save joyrexus/cb059ad8e54c3d7ad81a445b1f62f901 to your computer and use it in GitHub Desktop.

Revisions

  1. @moleike moleike revised this gist Apr 3, 2016. No changes.
  2. @moleike moleike revised this gist Apr 3, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions http-errors.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    'use strict';
    const statusCodes = require('http').STATUS_CODES;

    function createError(code, name) {
  3. @moleike moleike revised this gist Apr 1, 2016. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion http-errors.js
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@
    'use strict';
    const statusCodes = require('http').STATUS_CODES;

    function createError(code, name) {
  4. @moleike moleike revised this gist Apr 1, 2016. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion node-http-errors.md
    Original file line number Diff line number Diff line change
    @@ -19,7 +19,8 @@ try {

    ### Features

    * **4xx/5xx status as errors classes** - Status text is the class name, e.g. Unauthorized, NotFound
    * **4xx/5xx status as errors classes** - Status text is the class name, e.g. UnauthorizedError, NotFoundError
    * **Status code property** - Error handlers can use the status code to send responses.
    * **Correct stack trace** - no extra stack frames, no double capturing of the stack trace

    ### Anti-patterns
  5. @moleike moleike revised this gist Apr 1, 2016. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions node-http-errors.md
    Original file line number Diff line number Diff line change
    @@ -19,8 +19,7 @@ try {

    ### Features

    * **Name appears once** - less editing if you have to create lots of custom error classes
    * **Easy to subclass** - just change the last line to inherit from another custom error class you created
    * **4xx/5xx status as errors classes** - Status text is the class name, e.g. Unauthorized, NotFound
    * **Correct stack trace** - no extra stack frames, no double capturing of the stack trace

    ### Anti-patterns
  6. @moleike moleike renamed this gist Apr 1, 2016. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  7. @moleike moleike revised this gist Apr 1, 2016. 1 changed file with 8 additions and 3 deletions.
    11 changes: 8 additions & 3 deletions error.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,4 @@
    It's nice to be able to distinguish error types by classes. But it's a bit tricky to correctly create a custom error class in Node.js, so here is an example.

    The example also shows how to add an extra parameter called `extra` that will be stored as a property on the error.
    4xx/5xx errors with their statusCode in it.

    ### Usage

    @@ -10,6 +8,13 @@ var BadRequestError = require('./http-errors').BadRequestError;
    function doSomethingBad() {
    throw new BadRequestError('It went bad!');
    }

    try {
    doSomethingBad();
    } catch (err) {
    assert.strictEqual(err.statusCode, 400);
    }

    ```

    ### Features
  8. @moleike moleike revised this gist Apr 1, 2016. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions error.md
    Original file line number Diff line number Diff line change
    @@ -5,10 +5,10 @@ The example also shows how to add an extra parameter called `extra` that will be
    ### Usage

    ``` js
    var CustomError = require('./errors/custom-error');
    var BadRequestError = require('./http-errors').BadRequestError;

    function doSomethingBad() {
    throw new CustomError('It went bad!', 42);
    throw new BadRequestError('It went bad!');
    }
    ```

  9. @moleike moleike revised this gist Apr 1, 2016. 2 changed files with 1 addition and 1 deletion.
    File renamed without changes.
    2 changes: 1 addition & 1 deletion test-error.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // Mini test suite for our 4xx/5xx error

    var assert = require('assert');
    var BadRequestError = require('./errors').BadRequestError
    var BadRequestError = require('./http-errors').BadRequestError

    function doSomethingBad() {
    throw new BadRequestError('It went bad!');
  10. @moleike moleike revised this gist Apr 1, 2016. 3 changed files with 30 additions and 31 deletions.
    10 changes: 0 additions & 10 deletions custom-error.js
    Original file line number Diff line number Diff line change
    @@ -1,10 +0,0 @@
    'use strict';

    module.exports = function CustomError(message, extra) {
    Error.captureStackTrace(this, this.constructor);
    this.name = this.constructor.name;
    this.message = message;
    this.extra = extra;
    };

    require('util').inherits(module.exports, Error);
    21 changes: 21 additions & 0 deletions http-error.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,21 @@
    'use strict';
    const statusCodes = require('http').STATUS_CODES;

    function createError(code, name) {
    return function(message) {
    Error.captureStackTrace(this, this.constructor);
    this.name = name;
    this.message = message;
    this.statusCode = code;
    }
    }

    Object.keys(statusCodes)
    .filter(code => code >= 400)
    .forEach(code => {
    let name = statusCodes[code]
    .replace(/\W/g, '')
    .concat('Error')
    exports[name] = createError(Number(code), name);
    require('util').inherits(exports[name], Error);
    })
    30 changes: 9 additions & 21 deletions test-error.js
    Original file line number Diff line number Diff line change
    @@ -1,43 +1,31 @@
    // Mini test suite for our custom error
    // Mini test suite for our 4xx/5xx error

    var assert = require('assert');
    var CustomError = require('./errors/custom-error');
    var BadRequestError = require('./errors').BadRequestError

    function doSomethingBad() {
    throw new CustomError('It went bad!', 42);
    throw new BadRequestError('It went bad!');
    }

    try {
    doSomethingBad();
    } catch (err) {
    // The name property should be set to the error's name
    assert(err.name = 'CustomError');

    assert(err.name = 'BadRequestError');
    // The error should be an instance of its class
    assert(err instanceof CustomError);

    assert(err instanceof BadRequestError);
    // The error should be an instance of builtin Error
    assert(err instanceof Error);

    // The error should be recognized by Node.js' util#isError
    assert(require('util').isError(err));

    // The error should have recorded a stack
    assert(err.stack);

    // toString should return the default error message formatting
    assert.strictEqual(err.toString(),
    'CustomError: It went bad!');

    assert.strictEqual(err.toString(), 'BadRequestError: It went bad!');
    // The stack should start with the default error message formatting
    assert.strictEqual(err.stack.split('\n')[0],
    'CustomError: It went bad!');

    assert.strictEqual(err.stack.split('\n')[0], 'BadRequestError: It went bad!');
    // The first stack frame should be the function where the error was thrown.
    assert.strictEqual(err.stack.split('\n')[1].indexOf('doSomethingBad'), 7);

    // The extra property should have been set
    assert.strictEqual(err.extra, 42);
    }

    // Spoiler: It passes!
    assert.strictEqual(err.statusCode, 400);
    }
  11. @justmoon justmoon revised this gist Feb 1, 2015. 2 changed files with 18 additions and 5 deletions.
    9 changes: 4 additions & 5 deletions custom-error.js
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,10 @@
    module.exports = CustomError;
    'use strict';

    function CustomError(message, extra) {
    Error.call(this);
    module.exports = function CustomError(message, extra) {
    Error.captureStackTrace(this, this.constructor);
    this.name = this.constructor.name;
    this.message = message;
    this.extra = extra;
    }
    };

    require('util').inherits(CustomError, Error);
    require('util').inherits(module.exports, Error);
    14 changes: 14 additions & 0 deletions error.md
    Original file line number Diff line number Diff line change
    @@ -11,3 +11,17 @@ function doSomethingBad() {
    throw new CustomError('It went bad!', 42);
    }
    ```

    ### Features

    * **Name appears once** - less editing if you have to create lots of custom error classes
    * **Easy to subclass** - just change the last line to inherit from another custom error class you created
    * **Correct stack trace** - no extra stack frames, no double capturing of the stack trace

    ### Anti-patterns

    These are some things that I've seen in other proposed solutions that you should avoid.

    * `Error.call(this)` - creates another error object (wasting a bunch of time) and doesn't touch `this` at all
    * `Error.captureStackTrace(this, arguments.callee);` - works, but `arguments.callee` is deprecated, so don't use it
    * `this.stack = (new Error).stack` - this... I don't even...
  12. @justmoon justmoon revised this gist Feb 1, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions error.md
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,8 @@
    It's nice to be able to distinguish error types by classes. But it's a bit tricky to correctly create a custom error class in Node.js, so here is an example.

    This example also shows how to add an extra parameter called `extra` that will be stored as a property on the error.
    The example also shows how to add an extra parameter called `extra` that will be stored as a property on the error.

    Example usage:
    ### Usage

    ``` js
    var CustomError = require('./errors/custom-error');
  13. @justmoon justmoon revised this gist Feb 1, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion error.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    Sometimes you want to wrap error objects with application-specific errors for your stack traces.
    It's nice to be able to distinguish error types by classes. But it's a bit tricky to correctly create a custom error class in Node.js, so here is an example.

    This example also shows how to add an extra parameter called `extra` that will be stored as a property on the error.

  14. @justmoon justmoon revised this gist Feb 1, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions error.md
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@ Example usage:
    ``` js
    var CustomError = require('./errors/custom-error');

    function doSomethingRisky(callback) {
    throw new CustomError('You lost!', 42);
    function doSomethingBad() {
    throw new CustomError('It went bad!', 42);
    }
    ```
  15. @justmoon justmoon revised this gist Feb 1, 2015. 1 changed file with 43 additions and 0 deletions.
    43 changes: 43 additions & 0 deletions test-error.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    // Mini test suite for our custom error

    var assert = require('assert');
    var CustomError = require('./errors/custom-error');

    function doSomethingBad() {
    throw new CustomError('It went bad!', 42);
    }

    try {
    doSomethingBad();
    } catch (err) {
    // The name property should be set to the error's name
    assert(err.name = 'CustomError');

    // The error should be an instance of its class
    assert(err instanceof CustomError);

    // The error should be an instance of builtin Error
    assert(err instanceof Error);

    // The error should be recognized by Node.js' util#isError
    assert(require('util').isError(err));

    // The error should have recorded a stack
    assert(err.stack);

    // toString should return the default error message formatting
    assert.strictEqual(err.toString(),
    'CustomError: It went bad!');

    // The stack should start with the default error message formatting
    assert.strictEqual(err.stack.split('\n')[0],
    'CustomError: It went bad!');

    // The first stack frame should be the function where the error was thrown.
    assert.strictEqual(err.stack.split('\n')[1].indexOf('doSomethingBad'), 7);

    // The extra property should have been set
    assert.strictEqual(err.extra, 42);
    }

    // Spoiler: It passes!
  16. @justmoon justmoon revised this gist Feb 1, 2015. 2 changed files with 18 additions and 20 deletions.
    11 changes: 11 additions & 0 deletions custom-error.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    module.exports = CustomError;

    function CustomError(message, extra) {
    Error.call(this);
    Error.captureStackTrace(this, this.constructor);
    this.name = this.constructor.name;
    this.message = message;
    this.extra = extra;
    }

    require('util').inherits(CustomError, Error);
    27 changes: 7 additions & 20 deletions error.md
    Original file line number Diff line number Diff line change
    @@ -1,26 +1,13 @@
    Sometimes you want to wrap error objects with application-specific errors for your stack traces.

    Your custom error constructor:

    ```
    function CustomError(e, extra) {
    Error.call(this);
    Error.captureStackTrace(this, CustomError);
    this.id = e.id;
    this.name = 'CustomError';
    this.message = e.message
    }
    require('util').inherits(CustomError, Error);
    ```
    This example also shows how to add an extra parameter called `extra` that will be stored as a property on the error.

    Example usage:

    function doWork(callback) {
    doErrorProneWork(funtion(err, result) {
    if (err) return callback(new CustomError(err));

    ...
    }
    }
    ``` js
    var CustomError = require('./errors/custom-error');

    function doSomethingRisky(callback) {
    throw new CustomError('You lost!', 42);
    }
    ```
  17. @subfuzion subfuzion created this gist Feb 26, 2014.
    26 changes: 26 additions & 0 deletions error.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    Sometimes you want to wrap error objects with application-specific errors for your stack traces.

    Your custom error constructor:

    ```
    function CustomError(e, extra) {
    Error.call(this);
    Error.captureStackTrace(this, CustomError);
    this.id = e.id;
    this.name = 'CustomError';
    this.message = e.message
    }
    require('util').inherits(CustomError, Error);
    ```

    Example usage:

    function doWork(callback) {
    doErrorProneWork(funtion(err, result) {
    if (err) return callback(new CustomError(err));

    ...
    }
    }