1.0.3 • Published 2 years ago

custom-error-utils v1.0.3

Weekly downloads
-
License
ISC
Repository
-
Last release
2 years ago

What?

A collection of utilities for creating and handling custom errors in javascript applications, with a focus on server side code.

These errors attempt to conform to the HTTP standard outlined here

Custom Errors

These extend the base Error and append some additional data, providing default error messages.

Client Errors

Errors indicating a mistake on the client side:

BadRequestError

Error indicating a malformed request:

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

const error1 = new BadRequestError()
console.log(error.statusCode) // 400
//..
throw new BadRequestError()
throw new BadRequestError('Oh no!') // custom error message
// ..
const error2 = new BadRequestError('Oh no!', {message: 'invalid text!'}) // thrown error can contain additional data for context
console.log(error2.data) // {message: 'invalid text!'}

ForbiddenError

The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it. A server that wishes to make public why the request has been forbidden can describe that reason in the response payload (if any).

If authentication credentials were provided in the request, the server considers them insufficient to grant access. The client SHOULD NOT automatically repeat the request with the same credentials. The client MAY repeat the request with new or different credentials. However, a request might be forbidden for reasons unrelated to the credentials.

An origin server that wishes to "hide" the current existence of a forbidden target resource MAY instead respond with a status code of 404 (Not Found).

throw new ForbiddenError()
throw new ForbiddenError('Oh no!') // custom error message

const error = new ForbiddenError()
console.log(error.statusCode) // 403
console.log(error.isClientError) // true
console.log(error.isServerError) // false

NotFoundError

The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. A 404 status code does not indicate whether this lack of representation is temporary or permanent; the 410 (Gone) status code is preferred over 404 if the origin server knows, presumably through some configurable means, that the condition is likely to be permanent.

throw new NotFoundError()
throw new NotFoundError('Oh no!') // custom error message

UnauthorizedError

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource. The server generating a 401 response MUST send a WWW-Authenticate header field (Section 4.1) containing at least one challenge applicable to the target resource.

If the request included authentication credentials, then the 401 response indicates that authorization has been refused for those credentials. The user agent MAY repeat the request with a new or replaced Authorization header field (Section 4.2). If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user agent SHOULD present the enclosed representation to the user, since it usually contains relevant diagnostic information.

throw new UnauthorizedError()
throw new UnauthorizedError('Oh no!') // custom error message

Server Errors

Errors indicating a mistake on the server side:

InternalServerError

The generic server error

The 501 (Not Implemented) status code indicates that the server does not support the functionality required to fulfill the request. This is the appropriate response when the server does not recognize the request method and is not capable of supporting it for any resource.

throw new InternalServerError()
throw new InternalServerError('Oh no!') // custom error message

const error = new InternalServerError()
console.log(error.isClientError) // false
console.log(error.isServerError) // true

UpstreamServerError

This doesn't directly correspond to the spec. The statusCode is 500, but it allows you to set the name of the service that's failing. This may be useful for logging purposes.

throw new UpstreamServerError()
throw new UpstreamServerError('Oh no!') // custom error message

const error = new UpstreamServerError('oops', 'captchaService')
console.log(error.failingService) // captchaService

Middleware

Error handling middleware for express applications, use like:

const express = require('express')
const {withErrorHandler} = require('./src/middleware/express')
const app = express()
const port = 3000

app.use(withErrorHandler())

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

the middleware will by default return a json response:

{ "error" : "the error message"}

with the status code if one is set.

The middleware can be configured with a returnValue parameter that can either be any serializable constant, or a function that accepts the error and returns a serializable constant:

const errorHandler = withErrorHandler({
  // parse the error and return this is something goes wrong
  returnValue: error => ({
    message: error.message,
    stack: error.stack,
    isSuccess: false
  })
})

  // return a single error message no matter what!
const errorHanldler = withErrorHandler({
  // parse the error and return this is something goes wrong
  returnValue: "you messed up!"
})

Note: If returnValue is a function and that function throws an error, the middleware will fall back to the default return message and do so silently!

The middleware can also accept a withError function, this lets you do some arbitrary thing with the error before returning.

function errorLogger(error) {
  if(error instanceof UpstreamServerError) {
    logger.error(`Upstream service failed: ${error.failingService || 'Unknown Service'}`)
  }
}

const errorHandler = withErrorHandler({
  // parse the error and return this is something goes wrong
  withError: errorLogger
})

withError can also be async

async function errorLogger(error) {
  if(error instanceof UpstreamServerError) {
    await notify(`Upstream service failed: ${error.failingService || 'Unknown Service'}`)
  }
}

const errorHandler = withErrorHandler({
  // parse the error and return this is something goes wrong
  withError: errorLogger
})

Note: If withError throws an error, that error will be swallowed SILENTLY! This is to ensure the express middleware chain completes as expected.

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago