Skip to content
Draft

Beta #12

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
80ff297
baseline for beta version
leftieFriele Oct 29, 2024
ef3ca14
chore: updating publish workflow
leftieFriele Oct 31, 2024
d29635b
chore(release): 1.0.0-beta.1 [skip ci]
semantic-release-bot Oct 31, 2024
1aab57c
chore: fixing package publish config
leftieFriele Oct 31, 2024
6f14c0a
fix: removing custom error
leftieFriele Nov 1, 2024
bf39661
chore(release): 1.0.0-beta.2 [skip ci]
semantic-release-bot Nov 1, 2024
3283f5f
fix: adding .metrics property and circuit breaker metrics
leftieFriele Nov 1, 2024
09d9e47
Merge pull request #14 from podium-lib/adding-metrics
leftieFriele Nov 4, 2024
6e5954b
chore(release): 1.0.0-beta.3 [skip ci]
semantic-release-bot Nov 4, 2024
c5ea66b
fix: supporting more request options and metrics on breaker events
leftieFriele Nov 6, 2024
1a62a07
fix: supporting more request options and metrics on breaker events
leftieFriele Nov 6, 2024
43efba5
chore(release): 1.0.0-beta.4 [skip ci]
semantic-release-bot Nov 6, 2024
5820d35
fix: adjusting abort controller implementation
leftieFriele Nov 7, 2024
16b65b5
fix: adding back breaker metrics tests
leftieFriele Nov 7, 2024
c82e580
chore(release): 1.0.0-beta.5 [skip ci]
semantic-release-bot Nov 7, 2024
201b92f
adding metrics on the requests
leftieFriele Nov 8, 2024
726e6ee
docs update
leftieFriele Nov 8, 2024
efe65e7
fix: updating metrics to collect better things
leftieFriele Nov 8, 2024
dbe5402
chore: fixing intablity in test
leftieFriele Nov 11, 2024
ede638b
fixing types
leftieFriele Nov 11, 2024
920867c
chore(release): 1.0.0-beta.6 [skip ci]
semantic-release-bot Nov 11, 2024
97180e3
fix: making .request return the entire response
leftieFriele Nov 12, 2024
2afb5a5
chore(release): 1.0.0-beta.7 [skip ci]
semantic-release-bot Nov 12, 2024
b60865e
removing fallback option
leftieFriele Nov 12, 2024
c283017
fixing fallback bug
leftieFriele Nov 12, 2024
c5ded43
fix removing success breaker event
leftieFriele Nov 12, 2024
f4ccca2
fix: bump
leftieFriele Nov 12, 2024
b41acde
chore(release): 1.0.0-beta.8 [skip ci]
semantic-release-bot Nov 12, 2024
37e61f4
chore: making the benchmarks run
leftieFriele Nov 18, 2024
5c5c673
improving benchmark docs
leftieFriele Nov 18, 2024
8c67e3d
fix: upgrading to undici v7
leftieFriele Jan 13, 2025
8cc8e78
Merge pull request #28 from podium-lib/undici-v7
leftieFriele Jan 13, 2025
9fff901
chore(release): 1.0.0-beta.9 [skip ci]
semantic-release-bot Jan 13, 2025
e53e4ec
chore: updated docs a bit
leftieFriele Jan 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ jobs:
- name: npm test
run: npm test

# - name: npx semantic-release
# run: npx semantic-release
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: npx semantic-release
run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
56 changes: 56 additions & 0 deletions BENCHMARKS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Benchmarks
## Running benchmarks

Benchmarks are run using the [cronometro](https://www.npmjs.com/package/cronometro) module.

First start the cluster
```sh
cd benchmarks
PORT=3030 node server
```
See [server options](#server-options) for details on how to start the server.

Open a new terminal session and run the benchmarks:
```sh
PORT=3030 node benchmark.js
```
You should see something similar to this:
```sh
┌──────────────────────────────┬─────────┬──────────────────┬───────────┬─────────────────────────┐
│ Tests │ Samples │ Result │ Tolerance │ Difference with slowest │
|──────────────────────────────|─────────|──────────────────|───────────|─────────────────────────|
│ http - no keepalive │ 1 │ 1563.48 req/sec │ ± 0.00 % │ - │
|──────────────────────────────|─────────|──────────────────|───────────|─────────────────────────|
│ fetch │ 1 │ 3702.40 req/sec │ ± 0.00 % │ + 136.81 % │
|──────────────────────────────|─────────|──────────────────|───────────|─────────────────────────|
│ http - keepalive │ 1 │ 5509.85 req/sec │ ± 0.00 % │ + 252.41 % │
|──────────────────────────────|─────────|──────────────────|───────────|─────────────────────────|
│ undici - pipeline │ 1 │ 6413.69 req/sec │ ± 0.00 % │ + 310.22 % │
|──────────────────────────────|─────────|──────────────────|───────────|─────────────────────────|
│ undici - request │ 1 │ 8025.89 req/sec │ ± 0.00 % │ + 413.34 % │
|──────────────────────────────|─────────|──────────────────|───────────|─────────────────────────|
│ podium-http-client - request │ 1 │ 80482.90 req/sec │ ± 0.00 % │ + 5047.68 % │
└──────────────────────────────┴─────────┴──────────────────┴───────────┴─────────────────────────┘
```

See [benchmark options](#benchmark-options) for details options when running the benchmark.

### Server options

| Name | Default | Description |
|-----------|---------------------|------------------------------|
| `PORT` | `3030` | Server port |
| `TIMEOUT` | `1` | Server delay |
| `WORKERS` | `os.cpus().length` | Number of workers to spin up |

### Benchmark options

| Name | Default | Description |
|-----------------|----- ---|--------------------------------|
| `SAMPLES` | `1` | Number of iterations pr sample |
| `ERROR_TRESHOLD` | `3` | Benchmark error threshold |
| `CONNECTIONS` | `50` | Undici: max sockets |
| `PIPELINING` | `10` | Unidici: pipelining config |
| `PARALLEL` | `100` | Number of workers to spawn |
| `HEADERS_TIMEOUT` | `0` | Undici: headers timeout |
| `BODY_TIMEOUT` | `0` | Unidic: body timeout |
64 changes: 64 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# [1.0.0-beta.9](https://github.com/podium-lib/http-client/compare/v1.0.0-beta.8...v1.0.0-beta.9) (2025-01-13)


### Bug Fixes

* upgrading to undici v7 ([8c67e3d](https://github.com/podium-lib/http-client/commit/8c67e3dc67db3a7085898aa287c01b5e00f6e8f2))

# [1.0.0-beta.8](https://github.com/podium-lib/http-client/compare/v1.0.0-beta.7...v1.0.0-beta.8) (2024-11-12)


### Bug Fixes

* bump ([f4ccca2](https://github.com/podium-lib/http-client/commit/f4ccca2ca82a78f278f1fc8f828074bb19eacb17))

# [1.0.0-beta.7](https://github.com/podium-lib/http-client/compare/v1.0.0-beta.6...v1.0.0-beta.7) (2024-11-12)


### Bug Fixes

* making .request return the entire response ([97180e3](https://github.com/podium-lib/http-client/commit/97180e3fb8b135fcd0cc4810148701f48b9db1dd))

# [1.0.0-beta.6](https://github.com/podium-lib/http-client/compare/v1.0.0-beta.5...v1.0.0-beta.6) (2024-11-11)


### Bug Fixes

* updating metrics to collect better things ([efe65e7](https://github.com/podium-lib/http-client/commit/efe65e7de5c3d4b3e11cb0f46a5adf9493cad51b))

# [1.0.0-beta.5](https://github.com/podium-lib/http-client/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2024-11-07)


### Bug Fixes

* adding back breaker metrics tests ([16b65b5](https://github.com/podium-lib/http-client/commit/16b65b513a1d6932316b781c4e675e0956a76691))
* adjusting abort controller implementation ([5820d35](https://github.com/podium-lib/http-client/commit/5820d35fb0be8afd4c4886997ec07f69ebf0b5b5))

# [1.0.0-beta.4](https://github.com/podium-lib/http-client/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2024-11-06)


### Bug Fixes

* supporting more request options and metrics on breaker events ([1a62a07](https://github.com/podium-lib/http-client/commit/1a62a07de4c070738cebdd9f02a9e73c7fab784f))
* supporting more request options and metrics on breaker events ([c5ea66b](https://github.com/podium-lib/http-client/commit/c5ea66b620cb5d5a3fec12b9be0735bb8d0ad6ee))

# [1.0.0-beta.3](https://github.com/podium-lib/http-client/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2024-11-04)


### Bug Fixes

* adding .metrics property and circuit breaker metrics ([3283f5f](https://github.com/podium-lib/http-client/commit/3283f5fbe139efeacd1cc67b0a576a3587b14acd))

# [1.0.0-beta.2](https://github.com/podium-lib/http-client/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2024-11-01)


### Bug Fixes

* removing custom error ([6f14c0a](https://github.com/podium-lib/http-client/commit/6f14c0a0f5e3c772ef78b4ec40ba2b6fd193a5a0))

# 1.0.0-beta.1 (2024-10-31)


### Features

* Initial commit ([bfc0570](https://github.com/podium-lib/http-client/commit/bfc05709128b591b3d71aeddc3a30749cd2cf4cf))
180 changes: 174 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,192 @@
# @podium/http-client

⚠️ This project is still work in progress, should not be used for anything just yet.
⚠️ This project is in beta, use at your own risk. Changes might occur.

Generic http client built on [undici](undici.nodejs.org/) with a circuit breaker, error handling and metrics out of the box.

[![Dependencies](https://img.shields.io/david/podium-lib/http-client.svg)](https://david-dm.org/podium-lib/http-client)
[![GitHub Actions status](https://github.com/podium-lib/http-client/workflows/Run%20Lint%20and%20Tests/badge.svg)](https://github.com/podium-lib/layout/actions?query=workflow%3A%22Run+Lint+and+Tests%22)
[![Known Vulnerabilities](https://snyk.io/test/github/podium-lib/http-client/badge.svg)](https://snyk.io/test/github/podium-lib/http-client)

`@podium/http-client` is a general purpost http client built on [undici] with a circuit breaker using [opossum], error handling and metrics out of the box.
It is used in [@podium/client] and provides the formentioned capabilities to the [@podium/layout] module.

There is nothing podium specific in the client, which means that you can use it anywhere you do a `fetch` or use some other library to get or send content over HTTP. With the circuit breaking capability, it is ideal for consuming services in a distrubuted system.

**Table of contents:**

- [Installing](#installation)
- [Usage](#usage)
- [API](#api)
- [Constructor](#constructor)
- [Methods](#methods)
- Exposed [metrics](#metrics)
- [Benchmarks](./BENCHMARKS.md)

## Installation

*Note!* Requires Node.js v20 or later.

```bash
$ npm install @podium/http-client
npm install @podium/http-client
```

## Usage

Here is how to instantiate the client to make a request for the configured resource.
```js
import client from '@podium/http-client';
const client = new HttpClient(options);

const response = await client.request({ path: '/', origin: 'https://host.domain' })
if (response.ok) {
//
}

await client.close();
```
Note that you have to call `.close` when the request is

### Aborting requests

If for whatever reason you want to be able to manually abort a request, you can send in an `AbortController`.
```js
import client from '@podium/http-client';
const client = new HttpClient(options);

const controller = new AbortController();
const response = await client.request({
path: '/',
origin: 'https://host.domain',
signal: controller.signal
});
// Abort the request.
controller.abort();
await client.close();
```

## API

### Constructor

```js
import client from '@podium/http-client';
const client = new HttpClient(options);
```

## Constructor
#### options

| option | default | type | required | details |
|---------------------|--------------|------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------|
| clientName | `''` | `string` | no | Client name |
| connections | `50` | `number` | no | See [connections](#connections) |
| keepAliveMaxTimeout | `undefined` | `number` | no | See [keepAliveMaxTimeout](#keepAliveMaxTimeout) |
| keepAliveTimeout | `undefined` | `number` | no | See [keepAliveTimeout](#keepAliveTimeout) |
| logger | `undefined ` | `object` | no | A logger which conform to a log4j interface |
| pipelining | `10` | `number` | no | See [pipelining](#pipelining) |
| reset | `2000` | `number` | no | Circuit breaker: How long, in milliseconds, to wait before a tripped circuit should be reset. |
| threshold | `25` | `number` | no | Circuit breaker: How many, in %, requests should error before the circuit should trip. Ex; when 25% of requests fail, trip the circuit. |
| throwOn400 | `false` | `boolean` | no | If the client should throw on HTTP 400 errors.If true, HTTP 400 errors will counts against tripping the circuit. |
| throwOn500 | `true` | `boolean` | no | If the client should throw on HTTP 500 errors.If true, HTTP 500 errors will counts against tripping the circuit. |
| timeout | `500` | `number` | no | Circuit breaker: How long, in milliseconds, a request can maximum take. Requests exceeding this limit counts against tripping the circuit. |


##### connections

Property is sent to the underlying http library.
See library docs on [connections](https://undici.nodejs.org/#/docs/api/Pool?id=parameter-pooloptions)


##### keepAliveMaxTimeout

Property is sent to the underlying http library.
See library docs on [keepAliveTimeout](https://undici.nodejs.org/#/docs/api/Client?id=parameter-clientoptions)

##### keepAliveMaxTimeout

Property is sent to the underlying http library.
See library docs on [keepAliveMaxTimeout](https://undici.nodejs.org/#/docs/api/Client?id=parameter-clientoptions)

##### logger

Any log4j compatible logger can be passed in and will be used for logging.
Console is also supported for easy test / development.

Example:

```js
import client from '@podium/http-client';
const client = new HttpClient({
logger: abslog(/* your logging library of choice **/),
});
```

Under the hood [abslog] is used to abstract out logging. Please see [abslog] for
further details.

##### pipelining

Property is sent to the underlying http library.
See library docs on [pipelining](https://undici.nodejs.org/#/?id=pipelining)

##### reset
Circuit breaker: How long, in milliseconds, to wait before a tripped circuit should be reset.

##### threshold

Circuit breaker: How many, in %, requests should error before the circuit should trip. Ex; when 25% of requests fail, trip the circuit.

##### timeout
Circuit breaker: How long, in milliseconds, a request can maximum take. Requests exceeding this limit counts against tripping the circuit.

##### throwOn400

If the client should throw on http 400 errors. If true, http 400 errors will count against tripping the circuit.

##### throwOn500
If the client should throw on http 500 errors. If true, http 500 errors will count against tripping the circuit.

### Methods

#### async request(options = {})

Sends a request using the passed in options object.

| name | type | description |
|-----------------|-----------------|-------------------------------------------------|
| headers | `object` | Object with key / value which are strings |
| method | `string` | HTTP method name |
| origin | `string \| URL` | Request origin, ex `https://server.domain:9090` |
| path | `string` | URL path, ex `/foo` |
| query | `object` | Object with key / value which are strings |
| redirectable | `boolean` | If we should follow redirects or not. |
| maxRedirections | `number` | Max number of redirects. |
| signal | `AbortSignal` | Abort signal for canceling requests. |
| throwable | `boolean` | If we should throw on errors. |

For a complete list of options, consult the [undici documentation](https://undici.nodejs.org/#/?id=undicirequesturl-options-promise).

#### async close()

Closes the client and all open connections.

### Metrics

The client expose a number of [@metrics/metric] to enabled developers to monitor its behaviour.

| name | type | description |
|---------------------------------|---------------|-----------------------------------------------------|
| `http_client_breaker_events` | `counter` | See [breaker metrics](#breaker-metrics) |
| `http_client_request_error` | `counter` | Counters the number of requests returning an error. |
| `http_client_request_duration` | `histogram` | Times the duration of all http requests. |

See the [MetricsJS](https://metrics-js.github.io) project for more documentation on the individual metrics.

#### Breaker metrics

The client has metrics for the following events: `open`, `closed`, `rejected`.
See [opossum] for more details on these events.

[@metrics/metric]: https://metrics-js.github.io/reference/metric/
[@podium/client]: https://github.com/podium-lib/client
[@podium/layout]: https://github.com/podium-lib/layout
[abslog]: https://github.com/trygve-lie/abslog 'abslog'
[undici]: https://undici.nodejs.org/
[opossum]: https://github.com/nodeshift/opossum/
Loading
Loading