vwo-fme-node-sdk
Version:
VWO Node/JavaScript SDK for Feature Management and Experimentation
214 lines • 11.1 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.NetworkClient = void 0;
/**
* Copyright 2024-2025 Wingify Software Pvt. Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var http = require("http");
var https = require("https");
var PromiseUtil_1 = require("../../../utils/PromiseUtil");
var Url_1 = require("../../../constants/Url");
var ResponseModel_1 = require("../models/ResponseModel");
var logger_1 = require("../../../packages/logger");
var LogMessageUtil_1 = require("../../../utils/LogMessageUtil");
var log_messages_1 = require("../../../enums/log-messages");
var EventEnum_1 = require("../../../enums/EventEnum");
/**
* Implements the NetworkClientInterface to handle network requests.
*/
var NetworkClient = /** @class */ (function () {
function NetworkClient() {
}
/**
* Performs a GET request using the provided RequestModel.
* @param {RequestModel} requestModel - The model containing request options.
* @returns {Promise<ResponseModel>} A promise that resolves to a ResponseModel.
*/
NetworkClient.prototype.GET = function (requestModel) {
var _this = this;
var attemptRequest = function (attempt) {
var deferred = new PromiseUtil_1.Deferred();
// Extract network options from the request model.
var networkOptions = requestModel.getOptions();
var responseModel = new ResponseModel_1.ResponseModel();
try {
// Choose HTTP or HTTPS client based on the scheme.
var httpClient = networkOptions.scheme === Url_1.HTTPS ? https : http;
// Perform the HTTP GET request.
var req = httpClient.get(networkOptions, function (res) {
responseModel.setStatusCode(res.statusCode);
var contentType = res.headers['content-type'];
var error;
var rawData = '';
// Check for expected content-type.
if (!/^application\/json/.test(contentType)) {
error = "Invalid content-type.\nExpected application/json but received ".concat(contentType, ". Status Code: ").concat(res === null || res === void 0 ? void 0 : res.statusCode);
}
if (error) {
// Log error and consume response data to free up memory.
res.resume();
return _this.retryOrReject(error, attempt, deferred, networkOptions, attemptRequest, requestModel.getRetryConfig());
}
res.setEncoding('utf8');
// Collect data chunks.
res.on('data', function (chunk) {
rawData += chunk;
});
// Handle the end of the response.
res.on('end', function () {
try {
var parsedData = JSON.parse(rawData);
// Check for successful response status.
if (responseModel.getStatusCode() < 200 || responseModel.getStatusCode() >= 300) {
var error_1 = "".concat(rawData, ", Status Code: ").concat(responseModel.getStatusCode());
// if status code is 400, reject the promise as it is a bad request
if (responseModel.getStatusCode() === 400) {
responseModel.setError(error_1);
deferred.reject(responseModel);
return;
}
return _this.retryOrReject(error_1, attempt, deferred, networkOptions, attemptRequest, requestModel.getRetryConfig());
}
responseModel.setData(parsedData);
deferred.resolve(responseModel);
}
catch (err) {
return _this.retryOrReject(err, attempt, deferred, networkOptions, attemptRequest, requestModel.getRetryConfig());
}
});
});
// Handle request timeout.
req.on('timeout', function () {
return _this.retryOrReject(new Error('timeout'), attempt, deferred, networkOptions, attemptRequest, requestModel.getRetryConfig());
});
req.on('error', function (err) {
return _this.retryOrReject(err, attempt, deferred, networkOptions, attemptRequest, requestModel.getRetryConfig());
});
}
catch (err) {
_this.retryOrReject(err, attempt, deferred, networkOptions, attemptRequest, requestModel.getRetryConfig());
}
return deferred.promise;
};
return attemptRequest(0);
};
/**
* Performs a POST request using the provided RequestModel.
* @param {RequestModel} request - The model containing request options.
* @returns {Promise<ResponseModel>} A promise that resolves or rejects with a ResponseModel.
*/
NetworkClient.prototype.POST = function (request) {
var _this = this;
var attemptRequest = function (attempt) {
var deferred = new PromiseUtil_1.Deferred();
var networkOptions = request.getOptions();
var responseModel = new ResponseModel_1.ResponseModel();
try {
// Choose HTTP or HTTPS client based on the scheme.
var httpClient = networkOptions.scheme === Url_1.HTTPS ? https : http;
// Perform the HTTP POST request.
var req = httpClient.request(networkOptions, function (res) {
var rawData = '';
res.setEncoding('utf8');
// Collect data chunks.
res.on('data', function (chunk) {
rawData += chunk;
});
// Handle the end of the response.
res.on('end', function () {
try {
if (res.statusCode === 200) {
responseModel.setStatusCode(res.statusCode);
responseModel.setData(request.getBody());
deferred.resolve(responseModel);
}
else {
var error = "Raw Data: ".concat(rawData, ", Status Code: ").concat(res.statusCode);
responseModel.setStatusCode(res.statusCode);
// if status code is 400, reject the promise as it is a bad request
if (res.statusCode === 400) {
responseModel.setError(error);
deferred.reject(responseModel);
return;
}
return _this.retryOrReject(error, attempt, deferred, networkOptions, attemptRequest, request.getRetryConfig());
}
}
catch (err) {
return _this.retryOrReject(err, attempt, deferred, networkOptions, attemptRequest, request.getRetryConfig());
}
});
});
// Handle request timeout.
req.on('timeout', function () {
var error = "Timeout: ".concat(networkOptions.timeout);
return _this.retryOrReject(error, attempt, deferred, networkOptions, attemptRequest, request.getRetryConfig());
});
req.on('error', function (err) {
return _this.retryOrReject(err, attempt, deferred, networkOptions, attemptRequest, request.getRetryConfig());
});
// Write data to the request body and end the request.
req.write(JSON.stringify(networkOptions.body));
req.end();
}
catch (err) {
_this.retryOrReject(err, attempt, deferred, networkOptions, attemptRequest, request.getRetryConfig());
}
return deferred.promise;
};
return attemptRequest(0);
};
/**
* Helper function to retry or reject
* @param {any} error - The error to retry or reject
* @param {number} attempt - The attempt number
* @param {any} deferred - The deferred object
* @param {string} operation - The operation to retry or reject
* @param {Function} attemptRequest - The function to attempt the request
*/
NetworkClient.prototype.retryOrReject = function (error, attempt, deferred, networkOptions, attemptRequest, retryConfig) {
var endpoint = String(networkOptions.path).split('?')[0];
var delay = retryConfig.initialDelay * Math.pow(retryConfig.backoffMultiplier, attempt) * 1000;
if (retryConfig.shouldRetry && attempt < retryConfig.maxRetries) {
logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.NETWORK_CALL_RETRY_ATTEMPT, {
endPoint: endpoint,
err: error,
delay: delay,
attempt: attempt + 1,
maxRetries: retryConfig.maxRetries,
}));
setTimeout(function () {
attemptRequest(attempt + 1)
.then(deferred.resolve)
.catch(deferred.reject);
}, delay);
}
else {
if (!String(networkOptions.path).includes(EventEnum_1.EventEnum.VWO_LOG_EVENT)) {
// only log error if the endpoint is not vwo_log event
logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.NETWORK_CALL_RETRY_FAILED, {
endPoint: endpoint,
err: error,
}));
}
var responseModel = new ResponseModel_1.ResponseModel();
responseModel.setError(error);
deferred.reject(responseModel);
}
};
return NetworkClient;
}());
exports.NetworkClient = NetworkClient;
//# sourceMappingURL=NetworkClient.js.map
;