2019-11-02 00:06:25 +01:00
|
|
|
const pending_requests = [];
|
2014-02-07 04:27:16 +01:00
|
|
|
|
2016-12-05 07:02:18 +01:00
|
|
|
function add_pending_request(jqXHR) {
|
2014-02-07 04:27:16 +01:00
|
|
|
pending_requests.push(jqXHR);
|
|
|
|
if (pending_requests.length > 50) {
|
|
|
|
blueslip.warn('The length of pending_requests is over 50. Most likely ' +
|
|
|
|
'they are not being correctly removed.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-05 07:02:18 +01:00
|
|
|
function remove_pending_request(jqXHR) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const pending_request_index = _.indexOf(pending_requests, jqXHR);
|
2015-11-10 19:01:34 +01:00
|
|
|
if (pending_request_index !== -1) {
|
2014-02-07 04:27:16 +01:00
|
|
|
pending_requests.splice(pending_request_index, 1);
|
|
|
|
}
|
|
|
|
}
|
2013-12-18 19:55:18 +01:00
|
|
|
|
2014-01-07 23:40:31 +01:00
|
|
|
function call(args, idempotent) {
|
2013-12-17 22:18:13 +01:00
|
|
|
// Wrap the error handlers to reload the page if we get a CSRF error
|
|
|
|
// (What probably happened is that the user logged out in another tab).
|
2019-11-02 00:06:25 +01:00
|
|
|
let orig_error = args.error;
|
2013-12-17 22:18:13 +01:00
|
|
|
if (orig_error === undefined) {
|
|
|
|
orig_error = function () {};
|
|
|
|
}
|
|
|
|
args.error = function wrapped_error(xhr, error_type, xhn) {
|
2014-02-07 04:27:16 +01:00
|
|
|
remove_pending_request(xhr);
|
|
|
|
|
2014-02-10 22:54:55 +01:00
|
|
|
if (xhr.status === 403) {
|
|
|
|
try {
|
2017-07-25 03:30:13 +02:00
|
|
|
if (JSON.parse(xhr.responseText).code === 'CSRF_FAILED') {
|
2015-11-30 17:47:19 +01:00
|
|
|
reload.initiate({immediate: true,
|
|
|
|
save_pointer: true,
|
|
|
|
save_narrow: true,
|
|
|
|
save_compose: true});
|
2014-02-10 22:54:55 +01:00
|
|
|
}
|
|
|
|
} catch (ex) {
|
|
|
|
blueslip.error('Unexpected 403 response from server',
|
|
|
|
{xhr: xhr.responseText,
|
|
|
|
args: args},
|
|
|
|
ex.stack);
|
|
|
|
}
|
2013-12-17 22:18:13 +01:00
|
|
|
}
|
|
|
|
return orig_error(xhr, error_type, xhn);
|
|
|
|
};
|
2019-11-02 00:06:25 +01:00
|
|
|
let orig_success = args.success;
|
2014-01-07 23:40:31 +01:00
|
|
|
if (orig_success === undefined) {
|
|
|
|
orig_success = function () {};
|
|
|
|
}
|
|
|
|
args.success = function wrapped_success(data, textStatus, jqXHR) {
|
2014-02-07 04:27:16 +01:00
|
|
|
remove_pending_request(jqXHR);
|
|
|
|
|
2014-01-07 23:40:31 +01:00
|
|
|
if (!data && idempotent) {
|
|
|
|
// If idempotent, retry
|
|
|
|
blueslip.log("Retrying idempotent" + args);
|
|
|
|
setTimeout(function () {
|
2019-11-02 00:06:25 +01:00
|
|
|
const jqXHR = $.ajax(args);
|
2014-02-07 04:27:16 +01:00
|
|
|
add_pending_request(jqXHR);
|
2014-01-07 23:40:31 +01:00
|
|
|
}, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return orig_success(data, textStatus, jqXHR);
|
|
|
|
};
|
2013-12-17 22:18:13 +01:00
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const jqXHR = $.ajax(args);
|
2014-02-07 04:27:16 +01:00
|
|
|
add_pending_request(jqXHR);
|
|
|
|
return jqXHR;
|
2013-12-18 19:55:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
exports.get = function (options) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const args = _.extend({type: "GET", dataType: "json"}, options);
|
2014-01-07 23:40:31 +01:00
|
|
|
return call(args, options.idempotent);
|
2013-12-18 19:55:18 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.post = function (options) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const args = _.extend({type: "POST", dataType: "json"}, options);
|
2014-01-07 23:40:31 +01:00
|
|
|
return call(args, options.idempotent);
|
2013-12-18 19:55:18 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.put = function (options) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const args = _.extend({type: "PUT", dataType: "json"}, options);
|
2014-01-07 23:40:31 +01:00
|
|
|
return call(args, options.idempotent);
|
2013-12-18 19:55:18 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// Not called exports.delete because delete is a reserved word in JS
|
|
|
|
exports.del = function (options) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const args = _.extend({type: "DELETE", dataType: "json"}, options);
|
2014-01-07 23:40:31 +01:00
|
|
|
return call(args, options.idempotent);
|
2013-12-18 19:55:18 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.patch = function (options) {
|
|
|
|
// Send a PATCH as a POST in order to work around QtWebkit
|
|
|
|
// (Linux/Windows desktop app) not supporting PATCH body.
|
|
|
|
if (options.processData === false) {
|
|
|
|
// If we're submitting a FormData object, we need to add the
|
|
|
|
// method this way
|
|
|
|
options.data.append("method", "PATCH");
|
2014-01-14 23:24:39 +01:00
|
|
|
} else {
|
|
|
|
options.data = _.extend({}, options.data, {method: 'PATCH'});
|
2013-12-18 19:55:18 +01:00
|
|
|
}
|
2014-01-07 23:40:31 +01:00
|
|
|
return exports.post(options, options.idempotent);
|
2013-12-18 19:55:18 +01:00
|
|
|
};
|
|
|
|
|
2014-03-13 15:32:44 +01:00
|
|
|
exports.xhr_error_message = function (message, xhr) {
|
|
|
|
if (xhr.status.toString().charAt(0) === "4") {
|
|
|
|
// Only display the error response for 4XX, where we've crafted
|
|
|
|
// a nice response.
|
2016-08-24 23:56:23 +02:00
|
|
|
message += ": " + JSON.parse(xhr.responseText).msg;
|
2014-03-13 15:32:44 +01:00
|
|
|
}
|
|
|
|
return message;
|
|
|
|
};
|
|
|
|
|
2019-10-25 09:45:13 +02:00
|
|
|
window.channel = exports;
|