@authx/http-proxy-resource
Version:
The AuthX proxy for resources is a flexible HTTP proxy designed to sit in front of a resource.
111 lines • 3.96 kB
JavaScript
import { EventEmitter } from "events";
export class AuthXKeyCache extends EventEmitter {
_config;
_fetchTimeout = null;
_fetchAbortController = null;
_fetchAbortTimeout = null;
active = false;
keys = null;
constructor(config) {
super();
this._config = config;
}
_fetch = async () => {
this._fetchTimeout = null;
// Don't fetch unless the cache is active.
if (!this.active) {
return;
}
this._fetchAbortController = new AbortController();
this._fetchAbortTimeout = setTimeout(() => {
if (this._fetchAbortController) {
this._fetchAbortController.abort();
}
}, (this._config.authxPublicKeyRefreshRequestTimeout || 30) * 1000);
try {
// Fetch the keys from AuthX.
const response = await (await fetch(this._config.authxUrl + "/graphql", {
signal: this._fetchAbortController.signal,
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: '{"query": "query { keys }"}',
})).json();
if (typeof response !== "object" || response === null) {
throw new Error("The response from AuthX is not an object.");
}
// Make sure we don't have any errors.
if ("errors" in response &&
response.errors &&
Array.isArray(response.errors) &&
response.errors[0])
throw new Error(response.errors[0]);
if (!("data" in response) ||
response.data === null ||
typeof response.data !== "object" ||
!("keys" in response.data) ||
!Array.isArray(response.data.keys)) {
throw new Error("The response from AuthX is missing keys.");
}
const keys = response.data.keys;
// Ensure that there is at least one valid key in the response.
if (!keys ||
!Array.isArray(keys) ||
!keys.length ||
!keys.every((k) => typeof k === "string")) {
throw new Error("An array of least one key must be returned by AuthX.");
}
if (!this.active) {
return;
}
// Cache the keys.
this.keys = keys;
// Fire off a ready event.
this.emit("ready");
// Fetch again in 1 minute.
if (this.active && !this._fetchTimeout) {
this._fetchTimeout = setTimeout(this._fetch, (this._config.authxPublicKeyRefreshInterval || 60) * 1000);
}
}
catch (error) {
this.emit("error", error);
// Fetch again in 10 seconds.
if (this.active && !this._fetchTimeout) {
this._fetchTimeout = setTimeout(this._fetch, (this._config.authxPublicKeyRetryInterval || 10) * 1000);
}
}
finally {
this._fetchAbortController = null;
clearTimeout(this._fetchAbortTimeout);
this._fetchAbortTimeout = null;
}
};
start() {
if (this.active)
return;
this.active = true;
this._fetch();
}
stop() {
if (!this.active)
return;
this.active = false;
// Clear any pending timeouts.
const timeout = this._fetchTimeout;
if (timeout) {
clearTimeout(timeout);
}
const abortTimeout = this._fetchAbortTimeout;
if (abortTimeout) {
clearTimeout(abortTimeout);
}
// Abort any in-flight key requests.
const abort = this._fetchAbortController;
if (abort) {
abort.abort();
}
this.keys = null;
}
}
//# sourceMappingURL=AuthXKeyCache.js.map