Git Product home page Git Product logo

http-errors's Introduction

http-errors

NPM Version NPM Downloads Node.js Version Build Status Test Coverage

Create HTTP errors for Express, Koa, Connect, etc. with ease.

Install

This is a Node.js module available through the npm registry. Installation is done using the npm install command:

$ npm install http-errors

Example

var createError = require('http-errors')
var express = require('express')
var app = express()

app.use(function (req, res, next) {
  if (!req.user) return next(createError(401, 'Please login to view this page.'))
  next()
})

API

This is the current API, currently extracted from Koa and subject to change.

Error Properties

  • expose - can be used to signal if message should be sent to the client, defaulting to false when status >= 500
  • 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 - 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])

Create a new error object with the given message msg. The error object inherits from createError.HttpError.

var err = createError(404, 'This video does not exist!')
  • status: 500 - the status code as a number
  • message - the message of the error, defaulting to node's text for that status code.
  • properties - custom properties to attach to the object

createError([status], [error], [properties])

Extend the given error object with createError.HttpError properties. This will not alter the inheritance of the given error object, and the modified error object is the return value.

fs.readFile('foo.txt', function (err, buf) {
  if (err) {
    if (err.code === 'ENOENT') {
      var httpError = createError(404, err, { expose: false })
    } else {
      var httpError = createError(500, err)
    }
  }
})
  • status - the status code as a number
  • error - the error object to extend
  • properties - custom properties to attach to the object

createError.isHttpError(val)

Determine if the provided val is an HttpError. This will return true if the error inherits from the HttpError constructor of this module or matches the "duck type" for an error this module creates. All outputs from the createError factory will return true for this function, including if an non-HttpError was passed into the factory.

new createError[code || name]([msg]))

Create a new error object with the given message msg. The error object inherits from createError.HttpError.

var err = new createError.NotFound()
  • code - the status code as a number
  • name - the name of the error as a "bumpy case", i.e. NotFound or InternalServerError.

List of all constructors

Status Code Constructor Name
400 BadRequest
401 Unauthorized
402 PaymentRequired
403 Forbidden
404 NotFound
405 MethodNotAllowed
406 NotAcceptable
407 ProxyAuthenticationRequired
408 RequestTimeout
409 Conflict
410 Gone
411 LengthRequired
412 PreconditionFailed
413 PayloadTooLarge
414 URITooLong
415 UnsupportedMediaType
416 RangeNotSatisfiable
417 ExpectationFailed
418 ImATeapot
421 MisdirectedRequest
422 UnprocessableEntity
423 Locked
424 FailedDependency
425 TooEarly
426 UpgradeRequired
428 PreconditionRequired
429 TooManyRequests
431 RequestHeaderFieldsTooLarge
451 UnavailableForLegalReasons
500 InternalServerError
501 NotImplemented
502 BadGateway
503 ServiceUnavailable
504 GatewayTimeout
505 HTTPVersionNotSupported
506 VariantAlsoNegotiates
507 InsufficientStorage
508 LoopDetected
509 BandwidthLimitExceeded
510 NotExtended
511 NetworkAuthenticationRequired

License

MIT

http-errors's People

Contributors

arlac77 avatar carpasse avatar dead-horse avatar dougwilson avatar iyuq avatar jeduan avatar jonathanong avatar krmannix avatar niftylettuce avatar pluma avatar rlidwka avatar snyamathi avatar stephenmathieson avatar tjmehta avatar tkrotoff avatar ulisesgascon avatar wesleytodd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

http-errors's Issues

Question: Support "errors" inside properties

Hi! I read issue #69 where it has been shared that it should be possible to do the following:

const errors = { name: ["required"] }
createError(400, 'validation error', { errors })

Am I correct to assume that this should give the following back?:

{
  error: "Bad Request",
  message: "validation error",
  errors: { name: ["required"] },
  statusCode: 400
}

Because if that should be the case, I am currently only getting

{
  error: "Bad Request",
  message: "validation error",
  statusCode: 400
}

I am wondering if I am misunderstanding this functionality or implementing it wrong.

Guard Error.captureStackTrace()

I'm trying to use this library in react-native. RN uses the V8 JS engine during development, but JSC for releases.

V8 supports Error.captureStackTrace(), but JSC doesn't.

Hence, unguarded use of Error.captureStackTrace() in the library causes a TypeError exception for release builds:

TypeError: Error.captureStackTrace is not a function. (In 'Error.captureStackTrace(o)', 'Error.captureStackTrace' is undefined)

Would it be possible to guard calls to captureStackTrace() in the library?

Here's an example: auth0/react-native-auth0#33

Inconsistent error property enumerability

You would expect these usages to log identically:

import createError from 'http-errors'

console.log(
  JSON.stringify(createError('Message 1.')),
  JSON.stringify(createError(new Error('Message 2.')))
)

They actually output this:

{"message":"Message 1."} {"expose":false,"statusCode":500,"status":500}

For context, I am attempting to do snapshot testing of errors that have been created various ways and am having many surprises.

httpError(N, error) is misleading if error is already an HTTP error

I would expect

httpError(500, httpError(402)).statusCode

to be 500, but it's 402.

(The use case here is that I have a try/catch statement that turns all exceptions into HTTP 500s by default, and it's not working correctly when the original exception is already an httpError.)

Interface changes

Based on #103

Users likely expect to be able to pass custom properties to errors when creating them via the shortcut methods such as createError.NotFound().

Proposed change would look something like:

const createError = require('http-errors')

createError.NotFound({message: "Aw shucks", data: { foo: "bar" } }) // does not work today

You need to use the createError({...}) form to pass custom properties to an error.

createError(404, {message: "Aw shucks", data: { foo: "bar" } })

There's a few caveats with the current implementation, namely you can't set status via properties.

createError({ status: 404, message: "Aw shucks", data: { foo: "bar" } })
// status is ignored, will create a 500 server error with provided message and data fields

There is also a very high arity for createError, which should be locked down into a stable interface.

(code)

for (var i = 0; i < arguments.length; i++) {
    var arg = arguments[i]
    var type = typeof arg
    if (type === 'object' && arg instanceof Error) {
      err = arg
      status = err.status || err.statusCode || status
    } else if (type === 'number' && i === 0) {
      status = arg
    } else if (type === 'string') {
      msg = arg
    } else if (type === 'object') {
      props = arg
    } else {
      throw new TypeError('argument #' + (i + 1) + ' unsupported type ' + type)
    }
  }

Any of these changes would be semver major. There aren't plans for a major release of http-errors yet, but these are things Im thinking about.

why did I put these both in one issue?

These are both topics related to the interfaces exposed by the library for accepting arguments, which can use some rethinking.

how to set response headers?

I want to set error response headers when an error occurred. Like Content-Type = application/json. When I passed the {'content-type': 'application/json; charset=utf-8'} as err.headers nothing changed.

let err = new Error("{message: 'error'}");
err.status = 405;
err.headers = {"content-type": 'application/json; charset=utf-8'};
err.expose = true;
throw err;

Thanks in advance.

instanceof HttpError not working when receiving error from other package

I'm not sure if this is specific to http-errors or to TypeScript, but this is the issue I'm having: it seems that instanceof doesn't work when I'm receiving a HttpError from another package.

To reproduce:

  • create a package with npm init
  • npm install typescript http-errors --save
  • npm install @types/http-errors --save-dev
  • add index.ts:
import * as httpErrors from "http-errors";

export function getError() {
    return new httpErrors.Unauthorized("Whatever");
}

To have exactly the same as I did, run ./node_modules/typescript/bin/tsc --init and change target from es5 to es6.

Now run npm link in the directory and create a new project somewhere else and npm link <first-package-name> to add a symlink in the node_modules directory.

In the new project, add some code like this:

import * as httpErrors from "http-errors";
import { getError } from "<first-package-name>";

const err1 = new httpErrors.Unauthorized("Foo");
console.log(err1 instanceof httpErrors.HttpError); // will output true

const err2 = getError();
console.log(err2 instanceof httpErrors.HttpError); // will output false!

Again, I'm not sure if this is TypeScript in general, or the way the code in http-errors is contructed. I'm no JS/TS expert, so I'm interested in your opinion/advice.

For your convenience, I've created a repo that you can just pull and then run node index.js.

err.headers standardization

koajs/koa#668

not sure how we can standardize this... last thing i want is for other people to use a different property name. also want all the text casing to be the same so people don't do:

err.headers = {
  'content-type': 'text',
  'Content-Type': 'application/json',
}

maybe set .headers = {} by default?

Include typescript typings in the package

Question: would it be possible to include the typescript typings, which are currently available via @types/http-errors, directly into the package?

And by that, also provide for commonjs default export support?

.expose: precedence of the options object

I think ignoring .expose in the options object is somewhat counter intuitive. What's your position on this?
We could do something like

err = err || new Error(msg || statuses[status]);
err.expose = status < 500;
for (var key in props) err[key] = props[key];
err.status = err.statusCode = status;

@jonathanong, @dead-horse

Support non-standard response codes

It's not unsual for APIs, especially private ones, to use non-standard response codes in the 400 range for specific errors. As is, the module does not allow this - it will convert any non-standard code to a 500. As an example here's what I'm doing in my app:

  var err = http_errors(471, 'Invalid API Key.')
  err.status = 471;

Ideally, in my opinion, there would be a way to pass an array of additional codes when requiring the library, which would allow us to easily have a JSON file containing our extended error codes while allowing the library to validate the code against the list of available/valid codes.

Arbitrary properties on new createError[code || name]([msg]))?

Would be useful if we could pass arbitrary properties to errors using constructors. e.g.:

new createError[code || name]([msg],[properties]))

this would match the createError function signature. For example, right now we can do:

  createError(402, 'Your balance is too low.', {
    detail: {
      currentBalance: 100,
      price: 150,
    },
  })

but not

  new createError.PaymentRequired('Your balance is too low.', {
    detail: {
      currentBalance: 100,
      price: 150,
    },
  })

extremely slow

Holy crap. Just requiring this module add an entire 5 seconds of start up time on my machine!!! I have not yet dug into it.

[Feature Request] Support "errors" inside properties

Hi,

is it possible to add an "errors" support to properties.
For example something like this:

const errors = { name: ["required"] }
new BadRequest('validation error', { errors })

Because now I must extend a BadRequest error like that:

createError.ValidationError = class ValidationError extends createError.BadRequest {
  constructor(message, errors) {
    super(message)
    this.errors = errors
  }
}

and IMHO it should be out of the box supported.
What do you think?

The second argument "Error" overwrites the first argument "status"

I am sorry if I had written rude things because I am poor at English.

When I specified Error as the second argument, there was a key like status or statusCode, so the status code of the first argument was overwritten.

Error is like this.

{ MessageRejected: Email address is not verified.....
    message: 'Rejected',
    code: 'ClientError',
    statusCode: 400}
    

And, I written the following code.

try {
    ....
} catch (e) {
    throw createError(500, e, { errors: [{ msg: 'sending mail was failed' }] })
}

In the case of the above error, the first argument is ignored and the return value of status is forced to 400.
And I return the status of the Error to the client, as the status code of the response.

This is caused by the following code.

  for (var i = 0; i < arguments.length; i++) {
    var arg = arguments[i]
    if (arg instanceof Error) {
      err = arg
      status = err.status || err.statusCode || status

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I think it's strange that status was changed by the first argument , but it will changed again.

Constructor api parity

The createError([status], [error], [properties]) api allows the user to specify properties,
e.g.: throw createError(404, "test", { expose: false }).

However, the constructor api new createError[code || name]([msg])) does not.

Is there a reason for this? I would like to be able to e.g.:
throw new createError.NotFound("test", { expose: false })

In my use case I would like to use the expose flag to determine if the error message should be exposed to the end-client. In some cases (e.g., auth) the 4xx client errors messages are sensitive so I'd like to return an ambiguous message in the case that the http error doesn't have the expose flag set.

Consider replacing error factories with real constructors

Currently the "constructors" are actually just factory functions and we have a total of three such factories in the code that do pretty much the same thing (ClientError, ServerError and the exported function).

The only reason ServerError and ClientError have any inheritance at all is that the __proto__ property of the new error is manipulated directly. This is incompatible with some possible environments (the double underscores are there for a reason).

It would be nice if the two constructors were actual constructors (i.e. return this, not a retrofitted error). For an example of how this would work see [email protected].

The obvious drawback is that Object.prototype.toString returns [object Object] instead of [object Error] and util.isError returns false (though instanceof checks pass as one would expect). The benefit is that this approach can be made to work in environments that don't support overriding __proto__.

Consider un-deprecating non-error status codes

Currently throwing errors with non-error status codes works, but causes a deprecation notice to log:

screen shot 2018-06-07 at 12 27 48 am

There are instances where it is perfectly valid to throw an error yet respond with a 200 status. GraphQL servers are required to respond with a 200 status when errors were encountered within resolvers (see graphql/express-graphql#118 (comment)).

You can see this use case in action here: https://github.com/jaydenseric/graphql-api-koa/blob/v0.2.0/src/index.mjs#L182.

Support for Error.cause

Node 16.9 / V8 9.3 added a cause property to Error.

Can this support be added into this package? Even if it's not running a version that supports the extra Error constructor options, it would be good to attach it to HttpError.cause anyway.

Usability in browsers (wrap `captureStackTrace`)

Is it possible to check for the existence of Error.captureStackTrace() before using it?
I was trying to use http-errors on the browser side via Browserify, and it blew up with:

TypeError: Error.captureStackTrace is not a function

(on Firefox).
Any way to check for its existence before using, since it's non-standard to some environments?

params overloading

Is there any point in doing create(404, 'message') when you can use create[404]('message') ?

Also, you can do create(404, 'message') as well as create('message', 404), which will be pain to support if we decide to change that.

I'm now thinking about literally shadowing global Error object with this one:

var Error = require('http-error')
throw new Error('this would work as usual')
throw new Error[404]('this would work as http error')

... and things like treating numbers as status codes might break the idea.

A low-level question

When I use next (createError (500)) to create an httpError, and the error is returned to the client, will the remaining code on the server be stopped? Or will it return to the next place and continue to execute downward?

Feature Request: Ability to attach custom properties to named errors

Proposal

new createError.[code || name]([msg], [properties]))

Create a new error object with the given message msg.
The error object inherits from createError.HttpError.

var err1 = new createError.NotFound()
var err2 = new createError.NotImplemented('Route not implemented', { expose: true })
  • code - the status code as a number
  • name - the name of the error as a "bumpy case", i.e. NotFound or InternalServerError.
  • msg - (optional) the message of the error
  • properties - (optional) custom properties to attach to the object

Allow HttpError extension by ES6 classes

To allow better interoperability with ES6 classes (which are forced to call the super() constructor) it is better to add the following condition to the HttpError constructor:

if (this.constructor === HttpError) {
    throw new TypeError('cannot construct abstract class')
}

This way the class can be extended with a concrete class like this:

class MyHttpError extends HttpError {
    constructor() {
        super();
        ...
    }
}

A variant using ES6 classes as base class is shown here but the same works with old school constructor functions as well.

How to use error constructors directly

I noticed the docs don't mention using the named error constructors directly (i.e. new NotFound()). Is there a reason why? also since they are factories it seems that throw NotFound would be the call but ESLint balks at the capitalization. Is the future going to using these as legit constructors or heading towards a camelCase factory var?

The docs do not mention using the named constructor directly though the code exports them.

Add "expose" to "new createError.[code || name]([msg]))" syntax

Hi all,

Please consider add support for expose property in new createError.[code || name]([msg])) like syntax.

We use new createError.name([msg])) a lot because of its readability. It also mitigates the need to remember all those status codes. Being able to do something like below will be of great help.

var err = new createError.NotFound("Show this error to client.", {expose: true, ...});

Consider eval

Okay, I know how this sounds. Everybody knows eval is evil, but hear me out.

Currently errors created by this module have their constructor.name set to either Error or one of ServerError and ClientError (see my other ticket on consolidating the different factories).

It would be nice if they instead had the name that is used to export them, e.g. ImATeapot.

There is no way to set the name of a function after the fact, so this would require creating the constructors dynamically -- kinda like this.

The benefit would be that it would be easier to distinguish the various error functions exported by this module, especially in the console (where they currently just appear as [Function: ClientError] etc, rather than [Function: NotFound] and such).

Cannot install package due to flatmap-stream dependency

What I've done

I did an npm i http-errors@latest

Expected behavior

http-errors get installed, life goes on

What happened

The following error turned up

npm ERR! code E404
npm ERR! 404 Not Found: flatmap-stream@https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.1.tgz

Suggested Solution

Some dependency of the package has flatmap-stream as a dependency. Please update the dependencies

How to send the message in different structure ?

instead of :
if (!foundUser) return next(createError.NotFound("User not found"));

i want to send an object like this :

	if (!foundUser) return next(createError.NotFound(
		{
			field : "email",
			message: "User not found"
		}	
));

// the same as :  res.status(404).json({field:"email", message:"User not found"})

properties could change err.status

the test case will failed in koa:

describe('when props include status', function(){
    it('should be ignored', function(done){
      var ctx = context();

      try {
        ctx.throw(400, 'msg', {
          prop: true,
          status: -1
        });
      } catch (err) {
        assert('msg' == err.message);
        assert(400 == err.status);
        assert(true === err.expose);
        assert(true === err.prop);
        done();
      }
    })
  })

Is it intentional?

JSON stringified error does not contain message

In my app I use res.status(err.status).send(err) to send error. send uses JSON.stringify for objects. Stringified error does not contain message.

Example:

var createError = require('http-errors');

var error  = createError(404, 'message', { description: 'description' });
var error2 = createError(404, { message: 'message', description: 'description' });

console.log(JSON.stringify(error));  // {"description":"description"}
console.log(JSON.stringify(error2)); // {"description":"description"}

Always returning status code 500

validateId = (req, res, next) => {
    if (!mongoose.Types.ObjectId.isValid(req.params.id)) {
      return next(createError(404));
    }

    next();
  };

Getting

{
  "message": "Not Found",
  "name": "NotFoundError"
}

but with status code 500.

support new createError.BadRequest(obj)

some times we need to create an error, based on origin internal error.

so, I'd like to create error like this

catch (err) {
    if (err instanceof mongoose.Error.CastError) {
      throw new createError.BadRequest(err);
    } else ...;

Inconsistent error type

I'm trying to figure out how to identify the errors created with this library.

According to the README, "All errors inherit from JavaScript Error and the exported createError.HttpError." so my intention is to do something like

createError('...') instanceof createError.HttpError; // true

which works great unless an actual error is passed as an argument:

createError(new Error('...')) instanceof createError.HttpError; // false

In this case, createError() returns the original error instead (after adding some properties).

Because JS doesn't support multiple inheritance, I guess the remaining option is to rely on duck typing. For example:

const isHttpError = value => value instanceof Error && 'status' in value && 'expose' in value;

isHttpError(createError(new Error('...'))); // true

I wonder if this is the recommended approach and, if so, I'd suggest to update the documentation accordingly.

Cannot subclass errors

I was surprised I couldn't subclass errors. I would have expected my ValidationError class would support an instanceof check against itself.

const { BadRequest } = require('http-errors')
const assert = require('assert')


class ValidationError extends BadRequest {}

const err = new ValidationError()
console.log(err.name)
// "BadRequestError"

// err should be an instance of ValidationError
assert(err instanceof ValidationError)

https://runkit.com/cdignam-segment/6536e492c20c690008824a73

populateConstructorExports calls toIdentifier with unknown

After updating NPM packages, this exception started happening on each request.

TypeError: Cannot read properties of undefined (reading 'split')
  at toIdentifier (D:\home\site\wwwroot\node_modules\send\node_modules\toidentifier\index.js:24:6)
  at forEachCode (D:\home\site\wwwroot\node_modules\send\node_modules\http-errors\index.js:245:16)
  at Array.forEach (<anonymous>)
  at populateConstructorExports (D:\home\site\wwwroot\node_modules\send\node_modules\http-errors\index.js:243:9)
  at Object.<anonymous> (D:\home\site\wwwroot\node_modules\send\node_modules\http-errors\index.js:30:1)
  at Module._compile (node:internal/modules/cjs/loader:1101:14)
  at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
  at Module.load (node:internal/modules/cjs/loader:981:32)
  at Function.Module._load (node:internal/modules/cjs/loader:822:12)
  at Module.require (node:internal/modules/cjs/loader:1005:19)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.