ketting
Version:
Opinionated HATEOAS / Rest client.
74 lines • 2.51 kB
JavaScript
import problemFactory from './error.js';
import packageJson from 'ketting/package.json' with { type: 'json' };
/**
* The fetcher object is responsible for calling fetch()
*
* This is wrapped in an object because we want to support
* 'fetch middlewares'. These middlewares are similar to server-side
* middlewares and can intercept requests and alter requests/responses.
*/
export class Fetcher {
middlewares = [];
advertiseKetting = true;
/**
* A wrapper for MDN fetch()
*
* This wrapper supports 'fetch middlewares'. It will call them
* in sequence.
*/
fetch(resource, init) {
const request = new Request(resource, init);
const origin = new URL(request.url).origin;
const mws = this.getMiddlewaresByOrigin(origin);
mws.push((innerRequest) => {
if (!innerRequest.headers.has('User-Agent') && this.advertiseKetting) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
innerRequest.headers.set('User-Agent', `Ketting/${packageJson.version}`);
}
return fetch(innerRequest);
});
return invokeMiddlewares(mws, request);
}
/**
* Returns the list of middlewares that are applicable to
* a specific origin
*/
getMiddlewaresByOrigin(origin) {
return this.middlewares.filter(([regex]) => {
return regex.test(origin);
}).map(([, middleware]) => {
return middleware;
});
}
/**
* Add a middleware
*/
use(mw, origin = '*') {
const matchSplit = origin.split('*');
const matchRegex = matchSplit.map(part => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('(.*)');
const regex = new RegExp('^' + matchRegex + '$');
this.middlewares.push([regex, mw]);
}
/**
* Does a HTTP request and throws an exception if the server emitted
* a HTTP error.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Request/Request
*/
async fetchOrThrow(resource, init) {
const response = await this.fetch(resource, init);
if (response.ok) {
return response;
}
else {
throw await problemFactory(response);
}
}
}
export default Fetcher;
function invokeMiddlewares(mws, request) {
return mws[0](request, (nextRequest) => {
return invokeMiddlewares(mws.slice(1), nextRequest);
});
}
//# sourceMappingURL=fetcher.js.map