Skip to content

Commit 80ff297

Browse files
committed
baseline for beta version
1 parent 2a2787a commit 80ff297

File tree

7 files changed

+518
-81
lines changed

7 files changed

+518
-81
lines changed

README.md

Lines changed: 146 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,165 @@
22

33
⚠️ This project is still work in progress, should not be used for anything just yet.
44

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

7-
[![Dependencies](https://img.shields.io/david/podium-lib/http-client.svg)](https://david-dm.org/podium-lib/http-client)
87
[![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)
98
[![Known Vulnerabilities](https://snyk.io/test/github/podium-lib/http-client/badge.svg)](https://snyk.io/test/github/podium-lib/http-client)
109

1110
## Installation
1211

12+
*Note!* Requires Node.js v20 or later.
13+
1314
```bash
14-
$ npm install @podium/http-client
15+
npm install @podium/http-client
1516
```
1617

1718
## Usage
1819

20+
```js
21+
import client from '@podium/http-client';
22+
const client = new HttpClient(options);
23+
24+
const response = await client.request({ path: '/', origin: 'https://host.domain' })
25+
if (response.ok) {
26+
//
27+
}
28+
```
29+
30+
## API
31+
32+
### Constructor
1933

2034
```js
35+
import client from '@podium/http-client';
36+
37+
const client = new HttpClient(options);
38+
```
39+
40+
#### options
41+
42+
| option | default | type | required | details |
43+
|---------------------|--------------|------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------|
44+
| abortController | `undefined` | `object` | no | See [abortController](#abortController) |
45+
| connections | `50` | `number` | no | See [connections](#connections) |
46+
| fallback | `undefined` | `function` | no | Function to call when requests fail, see [fallback](#fallback) |
47+
| followRedirects | `false` | `boolean` | no | Flag for whether to follow redirects or not, see [followRedirects](#followRedirects). |
48+
| keepAliveMaxTimeout | `undefined` | `number` | no | See [keepAliveMaxTimeout](#keepAliveMaxTimeout) |
49+
| keepAliveTimeout | `undefined` | `number` | no | See [keepAliveTimeout](#keepAliveTimeout) |
50+
| logger | `undefined ` | `object` | no | A logger which conform to a log4j interface |
51+
| pipelining | `10` | `number` | no | See [pipelining](#pipelining) |
52+
| reset | `2000` | `number` | no | Circuit breaker: How long, in milliseconds, to wait before a tripped circuit should be reset. |
53+
| 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. |
54+
| throwOn400 | `false` | `boolean` | no | If the client should throw on HTTP 400 errors.If true, HTTP 400 errors will counts against tripping the circuit. |
55+
| throwOn500 | `true` | `boolean` | no | If the client should throw on HTTP 500 errors.If true, HTTP 500 errors will counts against tripping the circuit. |
56+
| timeout | `500` | `number` | no | Circuit breaker: How long, in milliseconds, a request can maximum take. Requests exceeding this limit counts against tripping the circuit. |
57+
58+
59+
##### abortController
60+
61+
Passing in an [AbortController](https://nodejs.org/docs/latest/api/globals.html#globals_class_abortcontroller) enables aborting requests.
62+
63+
##### connections
64+
65+
Property is sent to the underlying http library.
66+
See library docs on [connections](https://undici.nodejs.org/#/docs/api/Pool?id=parameter-pooloptions)
67+
68+
##### fallback
69+
70+
Optional function to run when a request fails.
71+
72+
```js
73+
// TBA
74+
```
75+
76+
##### followRedirects
77+
78+
TODO!!! decide what to do with the redirects stuff...
79+
80+
By default, the library does not follow redirect.
81+
If set to true it will follow redirects according to `maxRedirections`.
82+
It will by default throw on reaching `throwOnMaxRedirects`
83+
84+
85+
##### keepAliveMaxTimeout
86+
87+
Property is sent to the underlying http library.
88+
See library docs on [keepAliveTimeout](https://undici.nodejs.org/#/docs/api/Client?id=parameter-clientoptions)
89+
90+
##### keepAliveMaxTimeout
2191

92+
Property is sent to the underlying http library.
93+
See library docs on [keepAliveMaxTimeout](https://undici.nodejs.org/#/docs/api/Client?id=parameter-clientoptions)
94+
95+
##### logger
96+
97+
Any log4j compatible logger can be passed in and will be used for logging.
98+
Console is also supported for easy test / development.
99+
100+
Example:
101+
102+
```js
103+
const layout = new Layout({
104+
name: 'myLayout',
105+
pathname: '/foo',
106+
logger: console,
107+
});
22108
```
23109

24-
## Constructor
110+
Under the hood [abslog] is used to abstract out logging. Please see [abslog] for
111+
further details.
112+
113+
##### pipelining
114+
115+
Property is sent to the underlying http library.
116+
See library docs on [pipelining](https://undici.nodejs.org/#/?id=pipelining)
117+
118+
##### reset
119+
Circuit breaker: How long, in milliseconds, to wait before a tripped circuit should be reset.
120+
121+
##### threshold
122+
123+
Circuit breaker: How many, in %, requests should error before the circuit should trip. Ex; when 25% of requests fail, trip the circuit.
124+
125+
##### timeout
126+
Circuit breaker: How long, in milliseconds, a request can maximum take. Requests exceeding this limit counts against tripping the circuit.
127+
128+
##### throwOn400
129+
130+
If the client should throw on http 400 errors. If true, http 400 errors will count against tripping the circuit.
131+
132+
##### throwOn500
133+
If the client should throw on http 500 errors. If true, http 500 errors will count against tripping the circuit.
134+
135+
136+
137+
## Methods
138+
139+
### async request(options = {})
140+
141+
Sends a request using the passed in options object.
142+
143+
| name | type | description |
144+
|---------|-----------------|-------------------------------------------------|
145+
| origin | `string \| URL` | Request origin, ex `https://server.domain:9090` |
146+
| path | `string` | URL path, ex `/foo` |
147+
| method | `string` | HTTP method name |
148+
| headers | `object` | Object with key / value which are strings |
149+
| query | `object` | Object with key / value which are strings |
150+
| signal | `AbortSignal` | Abort signal for canceling requests. |
151+
152+
For a complete list of options, consult the [undici documentation](https://undici.nodejs.org/#/?id=undicirequesturl-options-promise).
153+
154+
155+
### async close()
156+
157+
Closes the client and it's connections.
158+
159+
## HttpClientError
160+
161+
Errors thrown from the library will be of the class `HttpClientError`
162+
163+
[@metrics/metric]: https://github.com/metrics-js/metric '@metrics/metric'
164+
[abslog]: https://github.com/trygve-lie/abslog 'abslog'
165+
[undici]: https://undici.nodejs.org/
166+
[opossum]: https://github.com/nodeshift/opossum/

examples/failing.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import HttpClient, { HttpClientError } from '../lib/http-client.js';
2+
3+
/**
4+
* Example of the circuit breaker opening on a failing request.
5+
*/
6+
const client = new HttpClient();
7+
try {
8+
await client.request({
9+
origin: 'http://localhost:9099',
10+
path: '/',
11+
method: 'GET',
12+
});
13+
// eslint-disable-next-line no-unused-vars
14+
} catch (_) {
15+
// Mute the first one, next request should hit an open breaker
16+
}
17+
18+
try {
19+
await client.request({
20+
origin: 'http://localhost:9099',
21+
path: '/',
22+
method: 'GET',
23+
});
24+
} catch (err) {
25+
if (err instanceof HttpClientError) {
26+
if (err.code === HttpClientError.ServerDown) {
27+
console.error('Server unavailable..');
28+
}
29+
}
30+
}

examples/success.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import HttpClient from '../lib/http-client.js';
2+
3+
const client = new HttpClient();
4+
const response = await client.request({
5+
origin: 'https://www.google.com',
6+
path: '/',
7+
method: 'GET',
8+
maxRedirections: 0,
9+
});
10+
11+
console.log(response.statusCode);

0 commit comments

Comments
 (0)