Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/fcmam5/nest-problem-details

A Nest.js HTTP exceptions filter returning RFC-7807 responses
https://github.com/fcmam5/nest-problem-details

api-rest hacktoberfest nest nestjs nodejs restful-api rfc-7807

Last synced: 3 months ago
JSON representation

A Nest.js HTTP exceptions filter returning RFC-7807 responses

Awesome Lists containing this project

README

        

# NestHttpProblemDetails(RFC-7807)

Make NestJS return [RFC-7807](https://datatracker.ietf.org/doc/html/rfc7807)-compliant HTTP problem details.


## Table of contents:

- [NestHttpProblemDetails(RFC-7807)](#nesthttpproblemdetailsrfc-7807)
- [Libraries](#libraries)
- [`nest-problem-details-filter`](#nest-problem-details-filter)
- [Usage](#usage)
- [As a global filter](#as-a-global-filter)
- [As a module](#as-a-module)
- [Example response](#example-response)
- [OpenAPI schema](#openapi-schema)
- [Example projects:](#example-projects)
- [Resources](#resources)
- [License](#license)

## Libraries

### [`nest-problem-details-filter`](./libs/nest-problem-details-filter/)

A NestJS exception filter to convert JSON responses to [RFC-7807](https://datatracker.ietf.org/doc/html/rfc7807)-compliant format. This standardizes HTTP responses and sets `Content-Type` to `application/problem+json`

#### Usage

Install the library with:

```bash
# npm
npm i nest-problem-details-filter

# or, pnpm
pnpm i nest-problem-details-filter
```

Then check [NestJS documentation](https://docs.nestjs.com/exception-filters#binding-filters) on how to bind exception filters.

##### As a global filter

In `main.ts` add `app.useGlobalFilters(new HttpExceptionFilter(app.getHttpAdapter()))` as the following

```ts
import { NestFactory } from '@nestjs/core';
import { HttpExceptionFilter } from 'nest-problem-details-filter';
import { AppModule } from './app/app.module';

async function bootstrap() {
...

const app = await NestFactory.create(AppModule);

app.useGlobalFilters(new HttpExceptionFilter(app.getHttpAdapter()));

...
}
```

`HttpExceptionFilter` accepts a base URI for if you want to return absolute URIs for your problem types, e.g:

```ts
app.useGlobalFilters(new HttpExceptionFilter('https://example.org'));
```

Will return:

```json
{
"type": "https://example.org/not-found",
"title": "Dragon not found",
"status": 404,
"detail": "Could not find any dragon with ID: 99"
}
```

##### As a module

The library can be imported as a module, and then can use `HTTP_EXCEPTION_FILTER_KEY` to set `APP_FILTER`

```typescript
import { APP_FILTER } from '@nestjs/core';
import {
NestProblemDetailsModule,
HTTP_EXCEPTION_FILTER_KEY,
} from 'nest-problem-details-filter';

@Module({
imports: [NestProblemDetailsModule],
...
providers: [
{
provide: APP_FILTER,
useExisting: HTTP_EXCEPTION_FILTER_KEY,
},
...
],
})
```

See:

- [Custom providers: Alias providers (`useExisting`)](https://docs.nestjs.com/fundamentals/custom-providers#alias-providers-useexisting)
- [Using `APP_FILTER` token](https://docs.nestjs.com/exception-filters#binding-filters)

### Example response

```bash
# curl -i http://localhost:3333/api/dragons/99?title=true&details=true

HTTP/1.1 404 Not Found
Content-Type: application/problem+json; charset=utf-8
Content-Length: 109
...

{
"type": "not-found",
"title": "Dragon not found",
"status": 404,
"detail": "Could not find any dragon with ID: 99"
}
```

### OpenAPI schema

```yml
# Source: https://opensource.zalando.com/restful-api-guidelines/problem-1.0.1.yaml
Problem:
type: object
properties:
type:
type: string
format: uri-reference
description: >
A URI reference that uniquely identifies the problem type only in the
context of the provided API. Opposed to the specification in RFC-7807,
it is neither recommended to be dereferencable and point to a
human-readable documentation nor globally unique for the problem type.
default: 'about:blank'
example: '/problem/connection-error'
title:
type: string
description: >
A short summary of the problem type. Written in English and readable
for engineers, usually not suited for non technical stakeholders and
not localized.
example: Service Unavailable
status:
type: integer
format: int32
description: >
The HTTP status code generated by the origin server for this occurrence
of the problem.
minimum: 100
maximum: 600
exclusiveMaximum: true
example: 503
detail:
type: string
description: >
A human readable explanation specific to this occurrence of the
problem that is helpful to locate the problem and give advice on how
to proceed. Written in English and readable for engineers, usually not
suited for non technical stakeholders and not localized.
example: Connection to database timed out
instance:
type: string
format: uri-reference
description: >
A URI reference that identifies the specific occurrence of the problem,
e.g. by adding a fragment identifier or sub-path to the problem type.
May be used to locate the root of this problem in the source code.
example: '/problem/connection-error#token-info-read-timed-out'
```

### Example projects:

- [`express-example-with-default-settings/`](./examples/express-example-with-default-settings/)
- [`fastify-example-with-default-settings/`](./examples/fastify-example-with-default-settings/)

## Resources

- [IETF RFC-7807: Problem Details for HTTP APIs](https://datatracker.ietf.org/doc/html/rfc7807)
- [Zalando RESTful API:](https://opensource.zalando.com/restful-api-guidelines/#176)
- And of course, Nest's awesome community:
- [Exception filters](https://docs.nestjs.com/exception-filters#exception-filters-1)
- [@kamilmysliwiec's comment](https://github.com/nestjs/nest/issues/2953#issuecomment-531678153)

## License

This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details