Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

rfc-7807-problem-details

ezzabuzaid105MIT1.2.0TypeScript support: included

Typescript implementation of rfc 7807

rfc-7807, problem details, node.js problem-details, nodejs problem-details, rfc-7807-problem-details

readme

Typescript implementation of RFC 7807 inspired from Hellang ProblemDetails

Install

npm i rfc-7807-problem-details
# Using Yarn
yarn add rfc-7807-problem-details

Problem details options

  • typePrefix - Reference
  • contentTypes - response content type, defaults to "application/problem+json"
  • mapStatusCode - a function that creates default problem details in case there's no mapping for the current error or the predicate mapping didn't pass
  • appendCacheHeaders - a function the add no cache response header
  • includeExceptionDetails - a function that determines whether to include exception details or not.
  • exceptionDetailsPropertyName - the property name that will have the error stack trace, defaults to exceptionDetails

Cache headers

By default these headers will be added

"cache-control": "no-cache, no-store, must-revalidate"
"pragma": "no-cache"
"etag": "0"
"expires": "0"

You can modify this behaviour by changing appendCacheHeaders option

// Default function
options.appendCacheHeaders = (setHeader) => {
    setHeader("cache-control", "no-cache, no-store, must-revalidate");
    setHeader("pragma", "no-cache");
    setHeader("etag", "0");
    setHeader("expires", "0");
};

// Do not add any cache header
options.appendCacheHeaders = (setHeader) => {};

// Add custom cache headers
options.appendCacheHeaders = (setHeader) => {
    setHeader("cache-control", "no-cache, no-store, must-revalidate");
    setHeader("pragma", "no-cache");
    setHeader("etag", "0");
    setHeader("expires", "0");
    setHeader("Last-Modified", "Wed, 21 Oct 2015 07:28:00 GMT"); // This line
};

Framework support

The library support Koa.js and express.js out of the box

  • Express
import express from "express";
import { problemDetailsMiddleware } from "rfc-7807-problem-details";
const app = express();

// Should be added at the last of the middleware chain
app.use(problemDetailsMiddleware.express());

Complete example

  • Koa
import Koa from "koa";
import { problemDetailsMiddleware } from "rfc-7807-problem-details";
const app = new Koa();

// Should be added at the start of the middleware chain
app.use(problemDetailsMiddleware.koa());

Complete example

  • Deno - Oak
import { Application } from "https://deno.land/x/oak/mod.ts";
import {
    ProblemDetailsException,
    ProblemDetailsOptions,
    ProblemDetailsSetup,
} from "https://esm.sh/rfc-7807-problem-details";
const app = new Application();

app.use(async (ctx, next) => {
    // set your options before constructing ProblemDetailsSetup
    const options = new ProblemDetailsOptions();
    options.typePrefix = `https://example.com/probs/out-of-credit`;

    const setup = new ProblemDetailsSetup(options);

    return async (context: any, next: any) => {
        try {
            await next();
        } catch (error) {
            options.appendCacheHeaders((name, value) =>
                ctx.response.headers.set(name, value)
            );

            const problem = setup.prepareProblemDetails(error, context);
            ctx.response.headers.set("content-type", options.contentTypes);
            context.status = problem.status;
            context.body = problem;
        }
    };
});

app.use(async (ctx, next) => {
    switch (ctx.request.url.pathname) {
        case "/example/throw":
            throw new ProblemDetailsException({
                type: "cannot-proceed",
                status: 400,
                title: "You cannot proceed.",
            });
        default:
            ctx.response.body = "Hello World";
            break;
    }
    await next();
});

await app.listen({ port: 8000 });

If you'd like to support custom framework take a look at the source code to see how you can do it.

For more examples check the demo directory.

changelog

1.1.0 (2022-05-18)

Features

  • export ProblemDetailsSetup class to handle custom/other frameworks (4cc8ff4)
  • prepare problem details option internally to reduce custom setup (85941a4)

Bug Fixes

  • incoming errors were not correctly checked using instanceof (4f230ed)
  • use context.set as default header setter (15f24cf)

1.0.2 (2022-05-15)

1.0.1 (2022-05-15)

Bug Fixes

  • remove support for isPorblem option (a48701f)

1.0.0 (2022-05-15)

⚠ BREAKING CHANGES

  • decouble middleware from problem details handling

Bug Fixes

  • decouble middleware from problem details handling (4e2ab91)
  • use instance of to find the correct constructor of error object (6708ba8)

0.2.5 (2022-05-14)

Bug Fixes

  • set detail to equal Error instance message if not present (3ef4419)

0.2.4 (2022-05-14)

Bug Fixes

  • make configure parameter optional (1d56139)

0.2.3 (2022-05-13)

Bug Fixes

  • pass problem details as is when passed to ProblemDetailsException (e83596d)

0.2.2 (2022-05-12)

Bug Fixes

  • ignore prefixing type if it starts with http or https (1b4c63a)

0.2.1 (2022-05-11)

Bug Fixes

  • set type to about:blank if not present (2496d8c)

0.2.0 (2022-05-11)

Features

  • add exception details (90fb76b)
  • add ProblemDetailsException (7c0da23)