Skip to content

Commit

Permalink
adding redirect support
Browse files Browse the repository at this point in the history
  • Loading branch information
leftieFriele committed Oct 30, 2024
1 parent d4968ac commit 5c00d48
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 11 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ const client = new HttpClient(options);

| option | default | type | required | details |
|---------------------|--------------|------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------|
| abortController | `undefined` | `object` | no | See [abortController](#abortController) |
| abortController | `undefined` | `object` | no | See [abortController](#abortController) |
| connections | `50` | `number` | no | See [connections](#connections) |
| fallback | `undefined` | `function` | no | Function to call when requests fail |
| fallback | `undefined` | `function` | no | Function to call when requests fail, see [fallback](#fallback) |
| followRedirects | `false` | `boolean` | no | Flag for whether to follow redirects or not, see [followRedirects](#followRedirects). |
| 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 |
Expand Down Expand Up @@ -72,6 +73,15 @@ Optional function to run when a request fails.
// TBA
```

##### followRedirects

TODO!!! decide what to do with the redirects stuff...

By default, the library does not follow redirect.
If set to true it will follow redirects according to `maxRedirections`.
It will by default throw on reaching `throwOnMaxRedirects`


##### keepAliveMaxTimeout

Property is sent to the underlying http library.
Expand Down
24 changes: 15 additions & 9 deletions lib/http-client.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Agent, request } from 'undici';
import { Agent, request, interceptors } from 'undici';
import createError from 'http-errors';
import Opossum from 'opossum';
import abslog from 'abslog';
Expand Down Expand Up @@ -35,6 +35,7 @@ export default class HttpClient {
autoRenewAbortController = false,
connections = 50,
fallback = undefined,
followRedirects = false,
keepAliveMaxTimeout = undefined,
keepAliveTimeout = undefined,
logger = undefined,
Expand Down Expand Up @@ -62,12 +63,19 @@ export default class HttpClient {
timeout,
});

this.#agent = new Agent({
keepAliveMaxTimeout, // TODO unknown option, consider removing
keepAliveTimeout, // TODO unknown option, consider removing
const { redirect } = interceptors;
let agent = new Agent({
keepAliveMaxTimeout,
keepAliveTimeout,
connections,
pipelining, // TODO unknown option, consider removing
pipelining,
});
if (followRedirects) {
agent = agent.compose(
redirect({ maxRedirections: 1, throwOnMaxRedirects: true }),
);
}
this.#agent = agent;

if (fallback) {
this.#hasFallback = true;
Expand All @@ -77,11 +85,8 @@ export default class HttpClient {

async #request(options = {}) {
const { statusCode, headers, trailers, body } = await request({
dispatcher: this.#agent,
...options,
dispatcher: new Agent({
keepAliveTimeout: 10,
keepAliveMaxTimeout: 10,
}),
});

if (this.#throwOn400 && statusCode >= 400 && statusCode <= 499) {
Expand Down Expand Up @@ -157,6 +162,7 @@ export default class HttpClient {
* Error class for the client
*/
export class HttpClientError extends Error {
// Not sure if there is a need for this tbh, but I threw it in there so we can see how it feels.
static ServerDown = 'EOPENBREAKER';
constructor(message, { code, cause, options }) {
super(message);
Expand Down
39 changes: 39 additions & 0 deletions tests/http-client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,45 @@ await test('http-client - abort controller', async (t) => {
slowServer.close();
});

await test('http-client - redirects', async (t) => {
const to = http.createServer(async (request, response) => {
response.writeHead(200);
response.end();
});
to.listen(3033, host);

const from = http.createServer(async (request, response) => {
if (request.url === '/redirect') {
response.setHeader('location', 'http://localhost:3033');
}
response.writeHead(301);
response.end();
});
from.listen(port, host);

await t.test('can follow redirects', async () => {
const client = new HttpClient({ threshold: 50, followRedirects: true });
const response = await client.request({
method: 'GET',
origin: `http://${host}:${port}`,
path: '/redirect',
});
assert.strictEqual(response.statusCode, 200);
});
// await t.test.skip('throw on max redirects', async () => {});
await t.test('does not follow redirects by default', async () => {
const client = new HttpClient({ threshold: 50 });
const response = await client.request({
method: 'GET',
origin: `http://${host}:${port}`,
path: '/redirect',
});
assert.strictEqual(response.statusCode, 301);
});
from.close();
to.close();
});

await test('http-client - circuit breaker behaviour', async (t) => {
const url = `http://${host}:${port}`;
await t.test('opens on failure threshold', async () => {
Expand Down

0 comments on commit 5c00d48

Please sign in to comment.