├── .gitignore ├── .travis.yml ├── README.md ├── examples └── express.js ├── index.js ├── package.json └── test ├── index.js └── mocha.opts /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "lts/*" 4 | - "4" 5 | - "5" 6 | - "6" 7 | - "7" 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pretty HTTP Errors for Node 2 | 3 | Ever wanted to build an API with Node and constantly had to either use blocks to return errors so you could attach a status code, or you just use one type of status code for all errors? Now you can throw your errors in just one line. 4 | 5 | `npm install node-http-error` 6 | 7 | [![Build Status](https://travis-ci.org/carsondarling/node-http-error.svg?branch=master)](https://travis-ci.org/carsondarling/node-http-errors) 8 | 9 | ## Example 10 | 11 | ```javascript 12 | var HTTPError = require('node-http-error'); 13 | var app = require('express')(); 14 | 15 | app.get('/error', function(req, req, next) { 16 | return next(new HTTPError(500, 'Error by design.')); 17 | }); 18 | 19 | // Error handler 20 | app.use(function(err, req, res, next) { 21 | res.status(err.status); // or use err.statusCode instead 22 | res.send(err.message); 23 | }); 24 | 25 | app.listen(2000); 26 | ``` 27 | 28 | ```shell 29 | $ curl -i http://localhost:2000/error 30 | 31 | HTTP/1.1 500 Internal Server Error 32 | X-Powered-By: Express 33 | Content-Type: application/json; charset=utf-8 34 | Content-Length: 51 35 | ETag: W/"33-2476597395" 36 | Date: Thu, 14 Aug 2014 17:51:07 GMT 37 | Connection: keep-alive 38 | 39 | Error by design. 40 | ``` 41 | 42 | ## Features 43 | 44 | - Treat it just like `Error`. `HTTPError`'s are throwable, have full stacktrace, and even print out their status code when they're thrown. 45 | - Don't worry about accidentally forgetting the `new` operator, HTTPError works without it. 46 | - Give it just the HTTP status code you want to return, and the error message is automatically generated. 47 | - Assign extra properties to the error. 48 | 49 | ## Usage 50 | 51 | #### `HTTPError(status, message, properties)` 52 | Creates an error with the given status, message and properties. For example 53 | 54 | new HTTPError(404, 'Not found!', { path: '/something-missing' }) 55 | 56 | #### `HTTPError(status, message)` 57 | Creates an error message with the given status and message. 58 | 59 | #### `HTTPError(message)` 60 | Creates an error message with the message and `500` as the status code (Internal Server Error). 61 | 62 | #### `HTTPError(status)` 63 | Creates an error message with the given status. The error message is looked up from the default Node HTTP module. For example, `HTTPError(404)` is equivalent to `HTTPError(404, 'Not Found')`. 64 | 65 | The Node HTTP module is not loaded unless needed to lookup the error message. 66 | -------------------------------------------------------------------------------- /examples/express.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Note: This project does not include Express as dependency for a variety of 3 | * reasons. If you want to run this example, make sure that you've installed 4 | * express. 5 | */ 6 | 7 | var HTTPError = require('../'); 8 | 9 | var express = require('express'); 10 | var app = express(); 11 | 12 | /** 13 | * Route that generates an error 14 | */ 15 | app.get('/error', function(req, req, next) { 16 | var shouldError = true; 17 | if (shouldError) return next(new HTTPError(500, 'Error by design.')); 18 | }); 19 | 20 | /** 21 | * Error logging 22 | */ 23 | app.use(function(err, req, res, next) { 24 | console.error(err); 25 | next(err); 26 | }); 27 | 28 | /** 29 | * Error response 30 | */ 31 | app.use(function(err, req, res, next) { 32 | 33 | var output = {error: { 34 | message: err.message 35 | }} 36 | 37 | if (err instanceof HTTPError) { 38 | res.status(err.status); 39 | output.error.status = err.status; 40 | } 41 | 42 | res.send(output); 43 | }); 44 | 45 | /** 46 | * Start app 47 | */ 48 | app.listen(2000); -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // Use lazy loading of the HTTP module only if we need to look up status codes 2 | var http; 3 | 4 | 5 | var HTTPError = module.exports = function HTTPError(status, message, properties) { 6 | // Make sure we're using the 'new' keyword 7 | if (!(this instanceof HTTPError)) return new HTTPError(status, message); 8 | 9 | // Do the argument shuffle. If a status code is given but no message, look up 10 | // the message from the Node.js HTTP module 11 | if (typeof status !== 'number') { 12 | message = status; 13 | status = null; 14 | } else { 15 | if (typeof message === 'undefined') { 16 | if (!http) { http = require('http'); } 17 | message = http.STATUS_CODES[status]; 18 | } 19 | } 20 | 21 | Error.call(this); //super constructor 22 | Error.captureStackTrace(this, this.constructor); 23 | 24 | // Setup error details 25 | this.name = this.constructor.name; 26 | this.status = this.statusCode = status || 500; 27 | this.message = message || ''; 28 | Object.assign(this, properties); 29 | }; 30 | 31 | 32 | // Set up inheritance 33 | HTTPError.prototype = Object.create(Error.prototype); 34 | HTTPError.prototype.constructor = HTTPError; 35 | 36 | 37 | // Formatting for error message 38 | HTTPError.prototype.toString = function() { 39 | return this.name + ': ' + this.status + ' ' + this.message; 40 | }; 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-http-error", 3 | "version": "2.0.0", 4 | "description": "Error subclasses for returning HTTP errors", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha" 8 | }, 9 | "author": "Carson Darling ", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "mocha": "^1.21.4", 13 | "should": "^4.0.4" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/carsondarling/node-http-error" 18 | }, 19 | "keywords": [ 20 | "error", 21 | "status code", 22 | "http" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var HTTPError = require('../'); 2 | var http = require('http'); 3 | 4 | describe('HTTPError', function() { 5 | it('should be throwable', function() { 6 | (function() { 7 | throw new HTTPError(404, 'Not found') 8 | }).should.throw(); 9 | }); 10 | 11 | it('should be an instance of Error', function() { 12 | var err = new HTTPError(404, 'Not found!'); 13 | err.should.be.instanceOf(Error); 14 | }); 15 | 16 | it('should be safe without the new operator', function() { 17 | var err = HTTPError(400, 'test'); 18 | (err instanceof HTTPError).should.be.true; 19 | err.message.should.eql('test'); 20 | err.status.should.eql(400); 21 | }); 22 | 23 | it('should have the correct message', function() { 24 | var err = new HTTPError(404, 'Not found!'); 25 | err.message.should.eql('Not found!'); 26 | }); 27 | 28 | it('should have the correct status code', function() { 29 | var err = new HTTPError(404, 'Not found!'); 30 | err.should.have.property('status'); 31 | err.status.should.eql(404); 32 | }); 33 | 34 | it('should allow statusCode as well as status', function() { 35 | var err = new HTTPError(404, 'Not found!'); 36 | err.should.have.property('statusCode'); 37 | err.statusCode.should.eql(err.status); 38 | }); 39 | 40 | it('should allow just a message', function() { 41 | var err = new HTTPError('test'); 42 | err.message.should.eql('test'); 43 | err.status.should.eql(500); 44 | }); 45 | 46 | it('should allow just a status code', function() { 47 | var err = new HTTPError(404); 48 | err.status.should.eql(404); 49 | }); 50 | 51 | it('should look up the correct status codes', function() { 52 | var codes = Object.keys(http.STATUS_CODES); 53 | codes = codes.map(function(code) { return parseInt(code) }); 54 | 55 | for (var i=0; i