js-standard-http-error-2.0.1/000077500000000000000000000000001315571571400160415ustar00rootroot00000000000000js-standard-http-error-2.0.1/.gitignore000066400000000000000000000000261315571571400200270ustar00rootroot00000000000000/node_modules/ /*.tgz js-standard-http-error-2.0.1/.npmignore000066400000000000000000000000241315571571400200340ustar00rootroot00000000000000/*.tgz /.travis.yml js-standard-http-error-2.0.1/.travis.yml000066400000000000000000000001741315571571400201540ustar00rootroot00000000000000sudo: false language: node_js node_js: - "stable" - "0.11" - "0.12" - "4" notifications: email: ["andri@dot.ee"] js-standard-http-error-2.0.1/CHANGELOG.md000066400000000000000000000047401315571571400176570ustar00rootroot00000000000000## 2.0.1 (Sep 12, 2017) - Removes a trailing comma for old Internet Explorer compatibility. ## 2.0.0 (Oct 4, 2015) - Updates HTTP status codes and constants from Node v4: Code | Old Name | New Name ------|-----------------------------------|--------- `302` | `MOVED_TEMPORARILY` | `FOUND` `408` | `REQUEST_TIME_OUT` | `REQUEST_TIMEOUT` `413` | `REQUEST_ENTITY_TOO_LARGE` | `PAYLOAD_TOO_LARGE` `414` | `REQUEST_URI_TOO_LARGE` | `URI_TOO_LONG` `416` | `REQUESTED_RANGE_NOT_SATISFIABLE` | `RANGE_NOT_SATISFIABLE` `504` | `GATEWAY_TIME_OUT` | `GATEWAY_TIMEOUT` ## 1.2.0 (Oct 4, 2015) - Restores status code names and constants to pre Node v4 times (Node v0.12) for backwards compatibility. Will release StandardHttpError.js v2 briefly with Node v4's names and constants. - Adds new status codes and constants from Node v4: Code | Name ------|----- `208` | `ALREADY_REPORTED` `226` | `IM_USED` `421` | `MISDIRECTED_REQUEST` `508` | `LOOP_DETECTED` - Makes `StandardHttpError` inherit from `StandardError` so you could more easily differentiate between bugs (usually thrown as `TypeError`, `SyntaxError` et al.) from user-facing errors that you've intentionally thrown. If all of your custom errors inherit from `StandardError` ([StandardError.js](https://github.com/moll/js-standard-error)), this will come in handy. ```javascript var StandardError = require("standard-error") var HttpError = require("standard-http-error") function magic(n) { if (isNaN(n)) throw new TypeError("Bug! Should never be NaN!") if (n <= 0) throw new HttpError(422, "Think positively!") // ... } try { magic(42) } catch (ex) { if (ex instanceof StandardError) console.error("Uh-oh: " + ex.message) else throw ex } ``` Make sure your dependencies have been deduped (see `npm dedupe`) to ensure a single `StandardError` instance (needed for `instanceof` to work) across your whole app. ## 1.1.1 (Jun 4, 2015) - Sets HttpError's name as a property on its prototype for when the code gets minified and the constructor name is changed. ## 1.1.0 (May 21, 2015) - Adds support for use in the browser by adding a cached copy of status codes. For example, use StandardHttpError.js with [Browserify](https://github.com/substack/node-browserify). ## 1.0.1 (Feb 23, 2015) - Fixes subclassing example in README. ## 1.0.0 (Feb 22, 2015) - Keep calm and invent a standard. js-standard-http-error-2.0.1/LICENSE000066400000000000000000000016631315571571400170540ustar00rootroot00000000000000StandardHttpError.js Copyright (C) 2015– Andri Möll This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. Additional permission under the GNU Affero GPL version 3 section 7: If you modify this Program, or any covered work, by linking or combining it with other code, such other code is not for that reason alone subject to any of the requirements of the GNU Affero GPL version 3. In summary: - You can use this program for no cost. - You can use this program for both personal and commercial reasons. - You do not have to share your own program's code which uses this program. - You have to share modifications (e.g bug-fixes) you've made to this program. For the full copy of the GNU Affero General Public License see: http://www.gnu.org/licenses. js-standard-http-error-2.0.1/Makefile000066400000000000000000000017071315571571400175060ustar00rootroot00000000000000NODE = node NODE_OPTS = TEST_OPTS = love: @echo "Feel like makin' love." test: @$(NODE) $(NODE_OPTS) ./node_modules/.bin/_mocha -R dot $(TEST_OPTS) spec: @$(NODE) $(NODE_OPTS) ./node_modules/.bin/_mocha -R spec $(TEST_OPTS) autotest: @$(NODE) $(NODE_OPTS) ./node_modules/.bin/_mocha -R dot --watch $(TEST_OPTS) autospec: @$(NODE) $(NODE_OPTS) ./node_modules/.bin/_mocha -R spec --watch $(TEST_OPTS) pack: @file=$$(npm pack); echo "$$file"; tar tf "$$file" constants: @$(NODE) -e '\ var ERRORS = require("./"); \ for (var name in ERRORS) console.log("`%d` | `%s`", ERRORS[name], name) \ ' codes.json: .FORCE $(NODE) -e 'console.log(JSON.stringify(require("http").STATUS_CODES, null, "\t"))' > "$@" publish: npm publish tag: git tag "v$$($(NODE) -e 'console.log(require("./package").version)')" clean: rm -f *.tgz npm prune --production .PHONY: love .PHONY: test spec autotest autospec .PHONY: pack publish tag .PHONY: clean .PHONY: .FORCE js-standard-http-error-2.0.1/README.md000066400000000000000000000171231315571571400173240ustar00rootroot00000000000000StandardHttpError.js ==================== [![NPM version][npm-badge]](https://www.npmjs.com/package/standard-http-error) [![Build status][travis-badge]](https://travis-ci.org/moll/js-standard-http-error) **StandardHttpError.js** is a very simple but useful **error class** for JavaScript and Node.js that represents HTTP errors. You can then detect it with `instanceof` in error handling middleware and act accordingly. Also works in the browser through [Browserify](http://browserify.org). You can use StandardHttpError.js with any error code you like, standardized or not. They don't have to exist beforehand, so if you're living on the cutting edge, feel free to use `new HttpError(451, "Unavailable For Legal Reasons")`. [npm-badge]: https://img.shields.io/npm/v/standard-http-error.svg [travis-badge]: https://travis-ci.org/moll/js-standard-http-error.png?branch=master Installing ---------- ```sh npm install standard-http-error ``` StandardHttpError.js follows [semantic versioning](http://semver.org/), so feel free to depend on its major version with something like `>= 1.0.0 < 2` (a.k.a `^1.0.0`). Using ----- ```javascript var HttpError = require("standard-http-error") throw new HttpError(404) ``` Your error handler will then receive an instance of `HttpError` along with the following enumerable properties: Property | Value ---------|------ name | `"HttpError"` code | `404` message | `"Not Found"` As always for errors, the non-enumerable `stack` property is there as well. For compatibility with Express or Koa's default request handler (the one that prints your errors out if you don't handle them), StandardHttpError.js also sets `status`, `statusCode` and `statusMessage` to be aliases of `code` and `message`. They're non-enumerable to not pollute serialization. ### Creating a new instance by error name StandardHttpError.js also supports passing a constant name instead of the error code. ```javascript new HttpError("NOT_FOUND") new HttpError("FORBIDDEN") ``` See below for a [list of error code names](#error-codes). ### Setting a custom message ```javascript new HttpError(412, "Bad CSRF Token") ``` The default "Precondition Failed" message that the error code 412 would've resulted in will then be replaced by "Bad CSRF Token". Note that status messages were always meant to be human readable, so it's perfect fine and even preferable to provide clarification in the status message. Try to stick to the capitalized form, though, as that will match the default HTTP status message style. ### Setting custom properties You can pass custom properties to be attached to the error instance as an object: ```javascript new HttpError(404, {url: req.url}) new HttpError(412, "Bad CSRF Token", {session: req.session}) ``` You can access the given `session` property then as `err.session`. ### Subclassing StandardHttpError If you wish to add your own functionality to StandardHttpError, subclass it: ```javascript var HttpError = require("standard-http-error") function RemoteError(res) { HttpError.call(this, res.statusCode, res.statusMessage) } RemoteError.prototype = Object.create(HttpError.prototype, { constructor: {value: RemoteError, configurable: true, writeable: true} }) ``` The [StandardError.js](https://github.com/moll/js-standard-error) library that StandardHttpError.js uses makes sure the `name` and `stack` properties of your new error class are set properly. If you don't want your new error class to directly inherit from `StandardHttpError`, feel free to leave the `RemoteError.prototype` line out. Everything will work as before except your `RemoteError` will no longer be an `instanceof` StandardHttpError.js. You might want to manually grab the `HttpError.prototype.toString` function then though, as that's useful for nice `String(err)` output. ### Switching based on error codes ```javascript switch (err.code) { case HttpError.UNAUTHORIZED: return void res.redirect("/signin") case HttpError.NOT_FOUND: return void res.render("404") case 451: return void res.redirect("/legal") default: return void res.render("500") } ``` ### Using with Express StandardHttpError.js comes very handy when used with Connect/Express's error handling functionality: ```javascript var HttpError = require("standard-http-error") var app = require("express")() app.get("/account", function(req, res, next) { if (req.account == null) throw new HttpError(401) if (req.account.budget == 0) throw new HttpError(402) // ... }) app.use(function(err, req, res, next) { if (!(err instanceof HttpError)) return void next(err) res.statusCode = err.code res.statusMessage = err.message res.render("error", {title: err.message}) }) ``` Error Codes ----------- StandardHttpError.js comes with a list of status message constants that you can use for comparison and in `switch` statements. ```javascript HttpError.NOT_FOUND // => 404 ``` When running on Node.js, cached status codes and their names get merged with new codes from `Http.STATUS_CODES`. Existing status codes will not be changed without bumping StandardHttpError.js's major version number. That ensures consistent constants in Node and in the browser. Code | Name ------|----- `100` | `CONTINUE` `101` | `SWITCHING_PROTOCOLS` `102` | `PROCESSING` `200` | `OK` `201` | `CREATED` `202` | `ACCEPTED` `203` | `NON_AUTHORITATIVE_INFORMATION` `204` | `NO_CONTENT` `205` | `RESET_CONTENT` `206` | `PARTIAL_CONTENT` `207` | `MULTI_STATUS` `208` | `ALREADY_REPORTED` `226` | `IM_USED` `300` | `MULTIPLE_CHOICES` `301` | `MOVED_PERMANENTLY` `302` | `FOUND` `303` | `SEE_OTHER` `304` | `NOT_MODIFIED` `305` | `USE_PROXY` `307` | `TEMPORARY_REDIRECT` `308` | `PERMANENT_REDIRECT` `400` | `BAD_REQUEST` `401` | `UNAUTHORIZED` `402` | `PAYMENT_REQUIRED` `403` | `FORBIDDEN` `404` | `NOT_FOUND` `405` | `METHOD_NOT_ALLOWED` `406` | `NOT_ACCEPTABLE` `407` | `PROXY_AUTHENTICATION_REQUIRED` `408` | `REQUEST_TIMEOUT` `409` | `CONFLICT` `410` | `GONE` `411` | `LENGTH_REQUIRED` `412` | `PRECONDITION_FAILED` `413` | `PAYLOAD_TOO_LARGE` `414` | `URI_TOO_LONG` `415` | `UNSUPPORTED_MEDIA_TYPE` `416` | `RANGE_NOT_SATISFIABLE` `417` | `EXPECTATION_FAILED` `418` | `IM_A_TEAPOT` `421` | `MISDIRECTED_REQUEST` `422` | `UNPROCESSABLE_ENTITY` `423` | `LOCKED` `424` | `FAILED_DEPENDENCY` `425` | `UNORDERED_COLLECTION` `426` | `UPGRADE_REQUIRED` `428` | `PRECONDITION_REQUIRED` `429` | `TOO_MANY_REQUESTS` `431` | `REQUEST_HEADER_FIELDS_TOO_LARGE` `500` | `INTERNAL_SERVER_ERROR` `501` | `NOT_IMPLEMENTED` `502` | `BAD_GATEWAY` `503` | `SERVICE_UNAVAILABLE` `504` | `GATEWAY_TIMEOUT` `505` | `HTTP_VERSION_NOT_SUPPORTED` `506` | `VARIANT_ALSO_NEGOTIATES` `507` | `INSUFFICIENT_STORAGE` `508` | `LOOP_DETECTED` `509` | `BANDWIDTH_LIMIT_EXCEEDED` `510` | `NOT_EXTENDED` `511` | `NETWORK_AUTHENTICATION_REQUIRED` License ------- StandardHttpError.js is released under a *Lesser GNU Affero General Public License*, which in summary means: - You **can** use this program for **no cost**. - You **can** use this program for **both personal and commercial reasons**. - You **do not have to share your own program's code** which uses this program. - You **have to share modifications** (e.g. bug-fixes) you've made to this program. For more convoluted language, see the `LICENSE` file. About ----- **[Andri Möll][moll]** typed this and the code. [Monday Calendar][monday] supported the engineering work. If you find StandardHttpError.js needs improving, please don't hesitate to type to me now at [andri@dot.ee][email] or [create an issue online][issues]. [email]: mailto:andri@dot.ee [issues]: https://github.com/moll/js-standard-http-error/issues [moll]: http://themoll.com [monday]: https://mondayapp.com js-standard-http-error-2.0.1/codes.js000066400000000000000000000002501315571571400174710ustar00rootroot00000000000000var CODES = require("http").STATUS_CODES exports = module.exports = require("./codes.json") for (var code in CODES) if (!(code in exports)) exports[code] = CODES[code] js-standard-http-error-2.0.1/index.js000066400000000000000000000027661315571571400175210ustar00rootroot00000000000000exports = module.exports = HttpError var StandardError = require("standard-error") var STATUS_CODE_TO_NAME = require("./codes") var STATUS_NAME_TO_CODE = exports function HttpError(code, msg, props) { if (typeof code == "string") code = STATUS_NAME_TO_CODE[code] if (typeof code != "number") throw new TypeError("Non-numeric HTTP code") if (typeof msg == "object" && msg != null) { props = msg; msg = null } StandardError.call(this, msg || STATUS_CODE_TO_NAME[code], props) this.code = code } HttpError.prototype = Object.create(StandardError.prototype, { constructor: {value: HttpError, configurable: true, writable: true} }) // Set name explicitly for when the code gets minified. HttpError.prototype.name = "HttpError" Object.defineProperties(HttpError.prototype, { statusCode: alias("code"), statusMessage: alias("message"), status: { configurable: true, get: function() { return this.code }, set: function(value) { Object.defineProperty(this, "status", { value: value, configurable: true, enumerable: true, writable: true }) } } }) HttpError.prototype.toString = function() { return this.name + ": " + this.code + " " + this.message } for (var code in STATUS_CODE_TO_NAME) { var name = STATUS_CODE_TO_NAME[code] exports[name.replace("'", "").replace(/[- ]/g, "_").toUpperCase()] = +code } function alias(name) { return { configurable: true, get: function() { return this[name] }, set: function(value) { return this[name] = value } } } js-standard-http-error-2.0.1/package.json000066400000000000000000000017421315571571400203330ustar00rootroot00000000000000{ "name": "standard-http-error", "version": "2.0.1", "description": "Standard HTTP error class. Proper serialization, no bloat. Extensible.", "keywords": [ "error", "errors", "http", "exception" ], "homepage": "https://github.com/moll/js-standard-http-error", "bugs": "https://github.com/moll/js-standard-http-error/issues", "author": { "name": "Andri Möll", "email": "andri@dot.ee", "url": "http://themoll.com" }, "repository": { "type": "git", "url": "git://github.com/moll/js-standard-http-error.git" }, "licenses": [{ "type": "LAGPL", "url": "https://github.com/moll/js-standard-http-error/blob/master/LICENSE" }], "main": "index.js", "scripts": {"test": "make test"}, "browser": { "./codes.js": "./codes.json" }, "dependencies": { "standard-error": ">= 1.1.0 < 2" }, "devDependencies": { "mocha": ">= 2.1.0 < 3", "must": ">= 0.12.0 < 0.13", "oolong": ">= 1.7.0 < 2", "http-codes": ">= 1.0.0 < 2", "semver": ">= 5 < 6" } } js-standard-http-error-2.0.1/test/000077500000000000000000000000001315571571400170205ustar00rootroot00000000000000js-standard-http-error-2.0.1/test/codes_test.js000066400000000000000000000011341315571571400215110ustar00rootroot00000000000000var O = require("oolong") var isVersion = require("semver").satisfies.bind(null, process.version) var CODES_JSON = require("../codes.json") var STATUS_CODES = require("http").STATUS_CODES ;(isVersion(">= 4") ? describe : xdescribe)("codes.json", function() { // Test for superset rather than equivalence because future Node versions // might _add_ status codes. During the switch from Node 0.12 to Node v4 some // names _were_ changed. O.each(STATUS_CODES, function(name, code) { it("must have " + code + " equal " + name, function() { CODES_JSON[code].must.equal(name) }) }) }) js-standard-http-error-2.0.1/test/index_test.js000066400000000000000000000134121315571571400215250ustar00rootroot00000000000000var O = require("oolong") var HttpError = require("..") var isVersion = require("semver").satisfies.bind(null, process.version) var describeNodeV4 = isVersion(">= 4 < 5") ? describe : xdescribe function RemoteError(code, msg, props) { HttpError.call(this, code, msg, props) } RemoteError.prototype = Object.create(HttpError.prototype, { constructor: {value: RemoteError, configurable: true, writeable: true} }) describe("HttpError", function() { describe("new", function() { it("must be an instance of HttpError", function() { new HttpError(400).must.be.an.instanceof(HttpError) }) it("must set code", function() { new HttpError(404).code.must.equal(404) }) it("must throw TypeError given undefined code", function() { (function() { new HttpError(undefined) }).must.throw(TypeError, /HTTP/) }) it("must throw TypeError given null code", function() { (function() { new HttpError(null) }).must.throw(TypeError, /HTTP/) }) it("must set code from constant name", function() { new HttpError("NOT_FOUND").code.must.equal(404) }) it("must throw TypeError given unknown constant", function() { (function() { new HttpError("DUNNO") }).must.throw(TypeError, /HTTP/) }) it("must set message from code", function() { new HttpError(404).message.must.equal("Not Found") }) it("must set message from code given null", function() { new HttpError(404, null).message.must.equal("Not Found") }) it("must set message from constant name", function() { new HttpError("NOT_FOUND").message.must.equal("Not Found") }) it("must set message if given", function() { new HttpError(404, "Dunno").message.must.equal("Dunno") }) it("must set name to HttpError", function() { new HttpError(400).name.must.equal("HttpError") }) it("must set name to constructor's name", function() { new RemoteError(400).name.must.equal("RemoteError") }) it("must set code, message and properties", function() { var err = new RemoteError(404, "Dunno", {url: "/dunno"}) err.code.must.equal(404) err.message.must.equal("Dunno") err.url.must.equal("/dunno") }) it("must set code and properties", function() { var err = new RemoteError(404, {url: "/dunno"}) err.code.must.equal(404) err.message.must.equal("Not Found") err.url.must.equal("/dunno") }) it("must set code and properties given null message", function() { var err = new RemoteError(404, null, {url: "/dunno"}) err.code.must.equal(404) err.message.must.equal("Not Found") err.url.must.equal("/dunno") }) it("must set stack", function() { var stack = new HttpError(400).stack.split(/\n\s*/) stack[0].must.equal("HttpError: Bad Request") stack[1].must.include("index_test.js") }) it("must set stack from constructor", function() { var stack = new RemoteError(400).stack.split(/\n\s*/) stack[0].must.equal("RemoteError: Bad Request") stack[1].must.include("index_test.js") stack[2].must.not.include("index_test.js") }) }) describe(".prototype.statusCode", function() { it("must be an alias to code", function() { var err = new HttpError(404) err.statusCode.must.equal(404) err.statusCode = 500 err.code.must.equal(500) }) it("must be non-enumerable", function() { new HttpError(412).must.have.nonenumerable("statusCode") }) }) describe(".prototype.statusMessage", function() { it("must be an alias to message", function() { var err = new HttpError(412, "Bad CSRF Token") err.statusMessage.must.equal("Bad CSRF Token") err.statusMessage = "Awful CSRF Token" err.message.must.equal("Awful CSRF Token") }) it("must be non-enumerable", function() { new HttpError(412).must.have.nonenumerable("statusMessage") }) }) describe(".prototype.status", function() { it("must be an alias to code", function() { new HttpError(404).status.must.equal(404) }) it("must be non-enumerable", function() { new HttpError(404).must.have.nonenumerable("status") }) it("must be overwritable", function() { var err = new HttpError(404) err.status = "OK" err.code.must.equal(404) err.status.must.equal("OK") var desc = Object.getOwnPropertyDescriptor(err, "status") desc.configurable.must.be.true() desc.writable.must.be.true() desc.enumerable.must.be.true() }) }) describe(".prototype.toString", function() { it("must return code and message", function() { new HttpError(404, "Dunno").toString().must.equal("HttpError: 404 Dunno") }) it("must use set name", function() { var err = new HttpError(404, "Dunno") err.name = "OtherError" err.toString().must.equal("OtherError: 404 Dunno") }) }) describe("HTTP status codes", function() { it("must have NOT_FOUND equal 404", function() { HttpError.must.have.property("NOT_FOUND", 404) }) it("must have INTERNAL_SERVER_ERROR equal 500", function() { HttpError.must.have.property("INTERNAL_SERVER_ERROR", 500) }) // Changed between Node v0.12 and Node v4. it("must have FOUND equal 302", function() { HttpError.must.have.property("FOUND", 302) new HttpError(302).message.must.equal("Found") }) describeNodeV4("when on Node v4", function() { var STATUS_NAMES = require("http-codes") // Fail safes: STATUS_NAMES.must.have.property("NOT_FOUND", 404) STATUS_NAMES.must.have.property("INTERNAL_SERVER_ERROR", 500) O.each(STATUS_NAMES, function(code, name) { it("must have " + name + " equal " + code, function() { HttpError[name].must.equal(code) }) }) }) }) }) js-standard-http-error-2.0.1/test/mocha.opts000066400000000000000000000000511315571571400210120ustar00rootroot00000000000000--recursive --check-leaks --require must