Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding fetch support for V3 #451

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 125 additions & 26 deletions lib/countly.js
Original file line number Diff line number Diff line change
Expand Up @@ -1831,9 +1831,9 @@
}
if (self.check_consent(featureEnums.REMOTE_CONFIG)) {
prepareRequest(request);
sendXmlHttpRequest("fetch_remote_config_explicit", self.url + readPath, request, function(err, params, responseText) {
makeNetworkRequest("fetch_remote_config_explicit", self.url + readPath, request, function(err, params, responseText) {
if (err) {
log(logLevelEnums.ERROR, "fetch_remote_config_explicit, An error occurred: " + err);
// error has been logged by the request function
return;
}
try {
Expand Down Expand Up @@ -1884,9 +1884,9 @@
av: self.app_version
};
prepareRequest(request);
sendXmlHttpRequest("enrollUserToAb", this.url + readPath, request, function(err, params, responseText) {
makeNetworkRequest("enrollUserToAb", this.url + readPath, request, function(err, params, responseText) {
if (err) {
log(logLevelEnums.ERROR, "enrollUserToAb, An error occurred: " + err);
// error has been logged by the request function
return;
}
try {
Expand Down Expand Up @@ -2837,9 +2837,9 @@
log(logLevelEnums.ERROR, "presentRatingWidgetWithID, Cannot show ratingWidget popup in offline mode");
}
else {
sendXmlHttpRequest("presentRatingWidgetWithID,", this.url + "/o/feedback/widget", { widget_id: id, av: self.app_version }, function(err, params, responseText) {
makeNetworkRequest("presentRatingWidgetWithID,", this.url + "/o/feedback/widget", { widget_id: id, av: self.app_version }, function(err, params, responseText) {
if (err) {
log(logLevelEnums.ERROR, "presentRatingWidgetWithID, An error occurred: " + err);
// error has been logged by the request function
return;
}
try {
Expand Down Expand Up @@ -2892,9 +2892,9 @@
stickers[0].remove();
}

sendXmlHttpRequest("initializeRatingWidgets,", this.url + "/o/feedback/multiple-widgets-by-id", { widgets: JSON.stringify(enableWidgets), av: self.app_version }, function(err, params, responseText) {
makeNetworkRequest("initializeRatingWidgets,", this.url + "/o/feedback/multiple-widgets-by-id", { widgets: JSON.stringify(enableWidgets), av: self.app_version }, function(err, params, responseText) {
if (err) {
log(logLevelEnums.ERROR, "initializeRatingWidgets, An error occurred: " + err);
// error has been logged by the request function
return;
}
try {
Expand Down Expand Up @@ -3013,9 +3013,9 @@
av: self.app_version
};

sendXmlHttpRequest("get_available_feedback_widgets,", url, data, function(err, params, responseText) {
makeNetworkRequest("get_available_feedback_widgets,", url, data, function(err, params, responseText) {
if (err) {
log(logLevelEnums.ERROR, "get_available_feedback_widgets, Error occurred while fetching feedbacks: " + err);
// error has been logged by the request function
if (callback) {
callback(null, err);
}
Expand Down Expand Up @@ -3086,7 +3086,7 @@
return;
}

sendXmlHttpRequest("getFeedbackWidgetData,", url, data, responseCallback, true);
makeNetworkRequest("getFeedbackWidgetData,", url, data, responseCallback, true);

/**
* Server response would be evaluated here
Expand All @@ -3096,7 +3096,7 @@
*/
function responseCallback(err, params, responseText) {
if (err) {
log(logLevelEnums.ERROR, "getFeedbackWidgetData, Error occurred while fetching feedbacks: " + err);
// error has been logged by the request function
if (callback) {
callback(null, err);
}
Expand Down Expand Up @@ -3915,11 +3915,10 @@
log(logLevelEnums.DEBUG, "Processing request", params);
setValueInStorage("cly_queue", requestQueue, true);
if (!self.test_mode) {
sendXmlHttpRequest("send_request_queue", self.url + apiPath, params, function(err, parameters) {
log(logLevelEnums.DEBUG, "Request Finished", parameters, err);
makeNetworkRequest("send_request_queue", self.url + apiPath, params, function(err, parameters) {

Check warning on line 3918 in lib/countly.js

View workflow job for this annotation

GitHub Actions / build-and-test (12.x)

'parameters' is defined but never used

Check warning on line 3918 in lib/countly.js

View workflow job for this annotation

GitHub Actions / build-and-test (14.x)

'parameters' is defined but never used

Check warning on line 3918 in lib/countly.js

View workflow job for this annotation

GitHub Actions / build-and-test (16.x)

'parameters' is defined but never used
if (err) {
// error has been logged by the request function
failTimeout = getTimestamp() + failTimeoutAmount;
log(logLevelEnums.ERROR, "Request error: ", err);
}
else {
// remove first item from queue
Expand Down Expand Up @@ -4130,6 +4129,24 @@
}
}

/**
* Decides to use which type of request method
* @memberof Countly._internals
* @param {String} functionName - Name of the function making the request for more detailed logging
* @param {String} url - URL where to make request
* @param {Object} params - key value object with URL params
* @param {Function} callback - callback when request finished or failed
* @param {Boolean} useBroadResponseValidator - if true that means the expected response is either a JSON object or a JSON array, if false only JSON
*/
function makeNetworkRequest(functionName, url, params, callback, useBroadResponseValidator) {
if (!isBrowser) {
sendFetchRequest(functionName, url, params, callback, useBroadResponseValidator);
}
else {
sendXmlHttpRequest(functionName, url, params, callback, useBroadResponseValidator);
}
}

/**
* Making xml HTTP request
* @memberof Countly._internals
Expand Down Expand Up @@ -4163,7 +4180,7 @@
// fallback on error
xhr.onreadystatechange = function() {
if (this.readyState === 4) {
log(logLevelEnums.DEBUG, functionName + " HTTP request completed [" + this.status + "][" + this.responseText + "]");
log(logLevelEnums.DEBUG, functionName + " HTTP request completed with status code: [" + this.status + "] and response: [" + this.responseText + "]");
// response validation function will be selected to also accept JSON arrays if useBroadResponseValidator is true
var isResponseValidated;
if (useBroadResponseValidator) {
Expand All @@ -4180,7 +4197,7 @@
}
}
else {
log(logLevelEnums.ERROR, functionName + " Failed Server XML HTTP request, ", this.status);
log(logLevelEnums.ERROR, functionName + " Invalid response from server");
if (functionName === "send_request_queue") {
HealthCheck.saveRequestCounters(this.status, this.responseText);
}
Expand All @@ -4199,7 +4216,90 @@
}
catch (e) {
// fallback
log(logLevelEnums.ERROR, functionName + " Failed XML HTTP request: " + e);
log(logLevelEnums.ERROR, functionName + " Something went wrong while making an XML HTTP request: " + e);
if (typeof callback === "function") {
callback(true, params);
}
}
}

/**
* Make a fetch request
* @memberof Countly._internals
* @param {String} functionName - Name of the function making the request for more detailed logging
* @param {String} url - URL where to make request
* @param {Object} params - key value object with URL params
* @param {Function} callback - callback when request finished or failed
* @param {Boolean} useBroadResponseValidator - if true that means the expected response is either a JSON object or a JSON array, if false only JSON
*/
function sendFetchRequest(functionName, url, params, callback, useBroadResponseValidator) {
useBroadResponseValidator = useBroadResponseValidator || false;
var response;

try {
log(logLevelEnums.DEBUG, "Sending Fetch request");

// Prepare request options
var method = "GET";
var headers = { "Content-type": "application/x-www-form-urlencoded" };
var body = null;

params = params || {};
if (self.force_post || prepareParams(params).length >= 2000) {
method = "POST";
body = prepareParams(params);
}
else {
url += "?" + prepareParams(params);
}

// Add custom headers
for (var header in self.headers) {
headers[header] = self.headers[header];
}

// Make the fetch request
fetch(url, {
method: method,
headers: headers,
body: body,
}).then(function(res) {
response = res;
return response.text();
}).then(function(data) {
log(logLevelEnums.DEBUG, functionName + " Fetch request completed wit status code: [" + response.status + "] and response: [" + data + "]");
var isResponseValidated;
if (useBroadResponseValidator) {
isResponseValidated = isResponseValidBroad(response.status, data);
}
else {
isResponseValidated = isResponseValid(response.status, data);
}

if (isResponseValidated) {
if (typeof callback === "function") {
callback(false, params, data);
}
}
else {
log(logLevelEnums.ERROR, functionName + " Invalid response from server");
if (functionName === "send_request_queue") {
HealthCheck.saveRequestCounters(response.status, data);
}
if (typeof callback === "function") {
callback(true, params, response.status, data);
}
}
}).catch(function(error) {
log(logLevelEnums.ERROR, functionName + " Failed Fetch request: " + error);
if (typeof callback === "function") {
callback(true, params);
}
});
}
catch (e) {
// fallback
log(logLevelEnums.ERROR, functionName + " Something went wrong with the Fetch request attempt: " + e);
if (typeof callback === "function") {
callback(true, params);
}
Expand All @@ -4218,7 +4318,7 @@
function isResponseValid(statusCode, str) {
// status code and response format check
if (!(statusCode >= 200 && statusCode < 300)) {
log(logLevelEnums.ERROR, "Http response status code is not within the expected range:[" + statusCode + "]");
log(logLevelEnums.ERROR, "Http response status code:[" + statusCode + "] is not within the expected range");
return false;
}

Expand Down Expand Up @@ -4252,7 +4352,7 @@
function isResponseValidBroad(statusCode, str) {
// status code and response format check
if (!(statusCode >= 200 && statusCode < 300)) {
log(logLevelEnums.ERROR, "Http response status code is not within the expected range: " + statusCode);
log(logLevelEnums.ERROR, "Http response status code:[" + statusCode + "] is not within the expected range");
return false;
}

Expand Down Expand Up @@ -4660,6 +4760,8 @@
userAgentSearchBotDetection: userAgentSearchBotDetection,
getRequestQueue: getRequestQueue,
getEventQueue: getEventQueue,
sendFetchRequest: sendFetchRequest,
makeNetworkRequest: makeNetworkRequest,
/**
* Clear queued data
* @memberof Countly._internals
Expand Down Expand Up @@ -4761,12 +4863,9 @@
// add common request params
prepareRequest(request);
// send request
sendXmlHttpRequest("[healthCheck]", self.url + apiPath, request, function(err, params, status, responseText) {
if (err) {
log(logLevelEnums.ERROR, "[healthCheck] An error occurred. Status: [" + status + "], response: [" + responseText + "]");
}
else {
log(logLevelEnums.INFO, "[healthCheck] Request was successful. Status: [" + status + "], response: [" + responseText + "]");
makeNetworkRequest("[healthCheck]", self.url + apiPath, request, function(err) {
// request maker already logs the error. No need to log it again here
if (!err) {
// reset and save health check counters if request was successful
HealthCheck.resetAndSaveCounters();
}
Expand Down
Loading