@selfage/node_service_client
Version:
Http client to make remote call to services from Nodejs applications.
105 lines • 16.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeServiceClient = void 0;
const EventEmitter = require("events");
const getStream = require("get-stream");
const http = require("http");
const http_error_1 = require("@selfage/http_error");
const serializer_1 = require("@selfage/message/serializer");
const stringifier_1 = require("@selfage/message/stringifier");
const service_descriptor_1 = require("@selfage/service_descriptor");
class NodeServiceClient extends EventEmitter {
static create(origin) {
return new NodeServiceClient(origin, (callback, ms) => setTimeout(callback, ms));
}
constructor(origin, setTimeout) {
super();
this.origin = origin;
this.setTimeout = setTimeout;
}
async send(request, options) {
try {
return await this.sendOrThrowErrors(request, options);
}
catch (e) {
if (e.statusCode) {
await Promise.all(this.listeners("httpError").map((callback) => callback(e)));
}
await Promise.all(this.listeners("error").map((callback) => callback(e)));
throw e;
}
}
async sendOrThrowErrors(request, options = {}) {
let headers = {};
let searchParams = new URLSearchParams();
if (request.metadata) {
searchParams.set(request.descriptor.metadata.key, (0, stringifier_1.stringifyMessage)(request.metadata, request.descriptor.metadata.type));
}
let writeBody;
if (request.descriptor.body.messageType) {
headers["content-type"] = "application/octet-stream";
writeBody = (req) => {
req.end((0, serializer_1.serializeMessage)(request.body, request.descriptor.body.messageType));
};
}
else if (request.descriptor.body.primitiveType === service_descriptor_1.PrimitveTypeForBody.BYTES) {
headers["content-type"] = "application/octet-stream";
writeBody = (req) => {
request.body.pipe(req);
};
}
else {
throw (0, http_error_1.newBadRequestError)("Unsupported client request body.");
}
let httpResponse = await this.requestWithTimeoutAndRetries(`${this.origin}${request.descriptor.service.path}${request.descriptor.path}`, searchParams, writeBody, headers, options.retries, options.timeout);
if (httpResponse.statusCode !== 200) {
let errorMessage = await getStream(httpResponse, {
encoding: "utf-8",
});
throw new http_error_1.HttpError(httpResponse.statusCode, errorMessage);
}
try {
return (0, serializer_1.deserializeMessage)(await getStream.buffer(httpResponse), request.descriptor.response.messageType);
}
catch (e) {
throw new Error(`Unable to parse server response.`);
}
}
async requestWithTimeoutAndRetries(url, searchParams, writeBody, headers, retries = 1, timeout) {
let lastError;
for (let i = 0; i < retries; i++) {
try {
let signal;
if (timeout) {
let abortController = new AbortController();
signal = abortController.signal;
this.setTimeout(() => abortController.abort(), timeout);
}
let res = await new Promise((resolve, reject) => {
let req = http.request(`${url}?${searchParams}`, {
method: "POST",
headers,
timeout,
signal,
}, (res) => resolve(res));
req.on("error", (e) => {
reject(e);
});
writeBody(req);
});
return res;
}
catch (e) {
if (e.code === "ABORT_ERR") {
throw new Error("Http request timed out.");
}
else {
lastError = e;
}
}
}
throw new Error(`Http request failed after ${retries} attempts. ${lastError}`);
}
}
exports.NodeServiceClient = NodeServiceClient;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHVDQUF3QztBQUN4Qyx3Q0FBeUM7QUFDekMsNkJBQThCO0FBQzlCLG9EQUFvRTtBQUNwRSw0REFHcUM7QUFDckMsOERBQWdFO0FBQ2hFLG9FQUFrRTtBQW9CbEUsTUFBYSxpQkFBa0IsU0FBUSxZQUFZO0lBQzFDLE1BQU0sQ0FBQyxNQUFNLENBQ2xCLE1BQWM7UUFFZCxPQUFPLElBQUksaUJBQWlCLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQ3BELFVBQVUsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQ3pCLENBQUM7SUFDSixDQUFDO0lBRUQsWUFDVSxNQUFjLEVBQ2QsVUFBc0Q7UUFFOUQsS0FBSyxFQUFFLENBQUM7UUFIQSxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2QsZUFBVSxHQUFWLFVBQVUsQ0FBNEM7SUFHaEUsQ0FBQztJQUVNLEtBQUssQ0FBQyxJQUFJLENBQ2YsT0FBeUMsRUFDekMsT0FBMkI7UUFFM0IsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDeEQsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDakIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUNmLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FDM0QsQ0FBQztZQUNKLENBQUM7WUFDRCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FB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QUFDO29CQUNOLFNBQVMsR0FBRyxDQUFDLENBQUM7Z0JBQ2hCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELE1BQU0sSUFBSSxLQUFLLENBQ2IsNkJBQTZCLE9BQU8sY0FBYyxTQUFTLEVBQUUsQ0FDOUQsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQXhJRCw4Q0F3SUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZShcImV2ZW50c1wiKTtcbmltcG9ydCBnZXRTdHJlYW0gPSByZXF1aXJlKFwiZ2V0LXN0cmVhbVwiKTtcbmltcG9ydCBodHRwID0gcmVxdWlyZShcImh0dHBcIik7XG5pbXBvcnQgeyBIdHRwRXJyb3IsIG5ld0JhZFJlcXVlc3RFcnJvciB9IGZyb20gXCJAc2VsZmFnZS9odHRwX2Vycm9yXCI7XG5pbXBvcnQge1xuICBkZXNlcmlhbGl6ZU1lc3NhZ2UsXG4gIHNlcmlhbGl6ZU1lc3NhZ2UsXG59IGZyb20gXCJAc2VsZmFnZS9tZXNzYWdlL3NlcmlhbGl6ZXJcIjtcbmltcG9ydCB7IHN0cmluZ2lmeU1lc3NhZ2UgfSBmcm9tIFwiQHNlbGZhZ2UvbWVzc2FnZS9zdHJpbmdpZmllclwiO1xuaW1wb3J0IHsgUHJpbWl0dmVUeXBlRm9yQm9keSB9IGZyb20gXCJAc2VsZmFnZS9zZXJ2aWNlX2Rlc2NyaXB0b3JcIjtcbmltcG9ydCB7IENsaWVudFJlcXVlc3RJbnRlcmZhY2UgfSBmcm9tIFwiQHNlbGZhZ2Uvc2VydmljZV9kZXNjcmlwdG9yL2NsaWVudF9yZXF1ZXN0X2ludGVyZmFjZVwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIE5vZGVDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllcz86IG51bWJlcjtcbiAgdGltZW91dD86IG51bWJlcjtcbn1cblxudHlwZSBXcml0ZUJvZHlGdW5jdGlvbiA9IChyZXE6IGh0dHAuQ2xpZW50UmVxdWVzdCkgPT4gdm9pZDtcblxuZXhwb3J0IGludGVyZmFjZSBOb2RlU2VydmljZUNsaWVudCB7XG4gIC8vIFdoZW4gc2VydmVyIGZpbmlzaGVkIHJlc3BvbnNlIHdpdGggYW4gZXJyb3IgY29kZSwgaS5lLiBlaXRoZXIgNHh4IG9yIDV4eC5cbiAgb24oXG4gICAgZXZlbnQ6IFwiaHR0cEVycm9yXCIsXG4gICAgbGlzdGVuZXI6IChlcnJvcjogSHR0cEVycm9yKSA9PiBQcm9taXNlPHZvaWQ+IHwgdm9pZCxcbiAgKTogdGhpcztcbiAgLy8gR2VuZXJhbCBlcnJvcnMgaW5jbHVkaW5nIGh0dHAgZXJyb3JzIGFuZCBuZXR3b3JrIGVycm9ycy5cbiAgb24oZXZlbnQ6IFwiZXJyb3JcIiwgbGlzdGVuZXI6IChlcnJvcjogYW55KSA9PiBQcm9taXNlPHZvaWQ+IHwgdm9pZCk6IHRoaXM7XG59XG5cbmV4cG9ydCBjbGFzcyBOb2RlU2VydmljZUNsaWVudCBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIHB1YmxpYyBzdGF0aWMgY3JlYXRlKFxuICAgIG9yaWdpbjogc3RyaW5nXG4gICk6IE5vZGVTZXJ2aWNlQ2xpZW50IHtcbiAgICByZXR1cm4gbmV3IE5vZGVTZXJ2aWNlQ2xpZW50KG9yaWdpbiwgKGNhbGxiYWNrLCBtcykgPT5cbiAgICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIG1zKSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgb3JpZ2luOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSBzZXRUaW1lb3V0OiAoY2FsbGJhY2s6IEZ1bmN0aW9uLCBtczogbnVtYmVyKSA9PiBudW1iZXIsXG4gICkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgc2VuZDxSZXNwb25zZT4oXG4gICAgcmVxdWVzdDogQ2xpZW50UmVxdWVzdEludGVyZmFjZTxSZXNwb25zZT4sXG4gICAgb3B0aW9ucz86IE5vZGVDbGllbnRPcHRpb25zLFxuICApOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnNlbmRPclRocm93RXJyb3JzKHJlcXVlc3QsIG9wdGlvbnMpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLnN0YXR1c0NvZGUpIHtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgdGhpcy5saXN0ZW5lcnMoXCJodHRwRXJyb3JcIikubWFwKChjYWxsYmFjaykgPT4gY2FsbGJhY2soZSkpLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwodGhpcy5saXN0ZW5lcnMoXCJlcnJvclwiKS5tYXAoKGNhbGxiYWNrKSA9PiBjYWxsYmFjayhlKSkpO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNlbmRPclRocm93RXJyb3JzKFxuICAgIHJlcXVlc3Q6IENsaWVudFJlcXVlc3RJbnRlcmZhY2U8YW55PixcbiAgICBvcHRpb25zOiBOb2RlQ2xpZW50T3B0aW9ucyA9IHt9LFxuICApOiBQcm9taXNlPGFueT4ge1xuICAgIGxldCBoZWFkZXJzOiBodHRwLk91dGdvaW5nSHR0cEhlYWRlcnMgPSB7fTtcbiAgICBsZXQgc2VhcmNoUGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcygpO1xuICAgIGlmIChyZXF1ZXN0Lm1ldGFkYXRhKSB7XG4gICAgICBzZWFyY2hQYXJhbXMuc2V0KFxuICAgICAgICByZXF1ZXN0LmRlc2NyaXB0b3IubWV0YWRhdGEua2V5LFxuICAgICAgICBzdHJpbmdpZnlNZXNzYWdlKHJlcXVlc3QubWV0YWRhdGEsIHJlcXVlc3QuZGVzY3JpcHRvci5tZXRhZGF0YS50eXBlKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgbGV0IHdyaXRlQm9keTogV3JpdGVCb2R5RnVuY3Rpb247XG4gICAgaWYgKHJlcXVlc3QuZGVzY3JpcHRvci5ib2R5Lm1lc3NhZ2VUeXBlKSB7XG4gICAgICBoZWFkZXJzW1wiY29udGVudC10eXBlXCJdID0gXCJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1cIjtcbiAgICAgIHdyaXRlQm9keSA9IChyZXEpID0+IHtcbiAgICAgICAgcmVxLmVuZChcbiAgICAgICAgICBzZXJpYWxpemVNZXNzYWdlKHJlcXVlc3QuYm9keSwgcmVxdWVzdC5kZXNjcmlwdG9yLmJvZHkubWVzc2FnZVR5cGUpLFxuICAgICAgICApO1xuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgcmVxdWVzdC5kZXNjcmlwdG9yLmJvZHkucHJpbWl0aXZlVHlwZSA9PT0gUHJpbWl0dmVUeXBlRm9yQm9keS5CWVRFU1xuICAgICkge1xuICAgICAgaGVhZGVyc1tcImNvbnRlbnQtdHlwZVwiXSA9IFwiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtXCI7XG4gICAgICB3cml0ZUJvZHkgPSAocmVxKSA9PiB7XG4gICAgICAgIHJlcXVlc3QuYm9keS5waXBlKHJlcSk7XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXdCYWRSZXF1ZXN0RXJyb3IoXCJVbnN1cHBvcnRlZCBjbGllbnQgcmVxdWVzdCBib2R5LlwiKTtcbiAgICB9XG5cbiAgICBsZXQgaHR0cFJlc3BvbnNlID0gYXdhaXQgdGhpcy5yZXF1ZXN0V2l0aFRpbWVvdXRBbmRSZXRyaWVzKFxuICAgICAgYCR7dGhpcy5vcmlnaW59JHtyZXF1ZXN0LmRlc2NyaXB0b3Iuc2VydmljZS5wYXRofSR7cmVxdWVzdC5kZXNjcmlwdG9yLnBhdGh9YCxcbiAgICAgIHNlYXJjaFBhcmFtcyxcbiAgICAgIHdyaXRlQm9keSxcbiAgICAgIGhlYWRlcnMsXG4gICAgICBvcHRpb25zLnJldHJpZXMsXG4gICAgICBvcHRpb25zLnRpbWVvdXQsXG4gICAgKTtcbiAgICBpZiAoaHR0cFJlc3BvbnNlLnN0YXR1c0NvZGUgIT09IDIwMCkge1xuICAgICAgbGV0IGVycm9yTWVzc2FnZSA9IGF3YWl0IGdldFN0cmVhbShodHRwUmVzcG9uc2UsIHtcbiAgICAgICAgZW5jb2Rpbmc6IFwidXRmLThcIixcbiAgICAgIH0pO1xuICAgICAgdGhyb3cgbmV3IEh0dHBFcnJvcihodHRwUmVzcG9uc2Uuc3RhdHVzQ29kZSwgZXJyb3JNZXNzYWdlKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGRlc2VyaWFsaXplTWVzc2FnZShcbiAgICAgICAgYXdhaXQgZ2V0U3RyZWFtLmJ1ZmZlcihodHRwUmVzcG9uc2UpLFxuICAgICAgICByZXF1ZXN0LmRlc2NyaXB0b3IucmVzcG9uc2UubWVzc2FnZVR5cGUsXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIHBhcnNlIHNlcnZlciByZXNwb25zZS5gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlcXVlc3RXaXRoVGltZW91dEFuZFJldHJpZXMoXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgc2VhcmNoUGFyYW1zOiBVUkxTZWFyY2hQYXJhbXMsXG4gICAgd3JpdGVCb2R5OiBXcml0ZUJvZHlGdW5jdGlvbixcbiAgICBoZWFkZXJzOiBodHRwLk91dGdvaW5nSHR0cEhlYWRlcnMsXG4gICAgcmV0cmllcyA9IDEsXG4gICAgdGltZW91dD86IG51bWJlcixcbiAgKTogUHJvbWlzZTxodHRwLkluY29taW5nTWVzc2FnZT4ge1xuICAgIGxldCBsYXN0RXJyb3I6IGFueTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJldHJpZXM7IGkrKykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGV0IHNpZ25hbDogQWJvcnRTaWduYWw7XG4gICAgICAgIGlmICh0aW1lb3V0KSB7XG4gICAgICAgICAgbGV0IGFib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICAgICAgICBzaWduYWwgPSBhYm9ydENvbnRyb2xsZXIuc2lnbmFsO1xuICAgICAgICAgIHRoaXMuc2V0VGltZW91dCgoKSA9PiBhYm9ydENvbnRyb2xsZXIuYWJvcnQoKSwgdGltZW91dCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHJlcyA9IGF3YWl0IG5ldyBQcm9taXNlPGh0dHAuSW5jb21pbmdNZXNzYWdlPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgbGV0IHJlcSA9IGh0dHAucmVxdWVzdChcbiAgICAgICAgICAgIGAke3VybH0/JHtzZWFyY2hQYXJhbXN9YCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgICAgICAgaGVhZGVycyxcbiAgICAgICAgICAgICAgdGltZW91dCxcbiAgICAgICAgICAgICAgc2lnbmFsLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIChyZXMpID0+IHJlc29sdmUocmVzKSxcbiAgICAgICAgICApO1xuICAgICAgICAgIHJlcS5vbihcImVycm9yXCIsIChlKSA9PiB7XG4gICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgd3JpdGVCb2R5KHJlcSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZS5jb2RlID09PSBcIkFCT1JUX0VSUlwiKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSHR0cCByZXF1ZXN0IHRpbWVkIG91dC5cIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbGFzdEVycm9yID0gZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgSHR0cCByZXF1ZXN0IGZhaWxlZCBhZnRlciAke3JldHJpZXN9IGF0dGVtcHRzLiAke2xhc3RFcnJvcn1gLFxuICAgICk7XG4gIH1cbn1cbiJdfQ==