Skip to content

Commit

Permalink
Enqueue requests made from QuickIcon plugins (#38019)
Browse files Browse the repository at this point in the history
* Enqueue requests made from QuickIcon plugins

Fix for gh-38001

* Also enqueue requests made be AJAX badges

AJAX badges appear in custom dashboards rendered by
com_cpanel, e.g. the System Dashboard.
  • Loading branch information
Nicholas K. Dionysopoulos committed Jun 12, 2022
1 parent 8c845cc commit d18db95
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Joomla.request({
url: badgeurl,
method: 'POST',
queued: true,
onSuccess: (resp) => {
let response;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@
}
};

/**
* DO NOT use fetch() for QuickIcon requests. They must be queued.
*
* @see https://github.com/joomla/joomla-cms/issues/38001
*/
Joomla.request({
url: options.ajaxUrl,
method: 'GET',
data: '',
perform: true,
queued: true,
onSuccess: (response) => {
const updateInfoList = JSON.parse(response);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,43 @@ if (Joomla && Joomla.getOptions('js-extensions-update')) {
const fetchUpdate = () => {
const options = Joomla.getOptions('js-joomla-update');

fetch(options.ajaxUrl, { method: 'GET' })
.then((response) => {
response.json().then((updateInfoList) => {
if (Array.isArray(updateInfoList)) {
if (updateInfoList.length === 0) {
// No updates
update('success', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_UPTODATE'));
} else {
const updateInfo = updateInfoList.shift();
/**
* DO NOT use fetch() for QuickIcon requests. They must be queued.
*
* @see https://github.com/joomla/joomla-cms/issues/38001
*/
Joomla.request({
url: options.ajaxUrl,
method: 'GET',
data: '',
perform: true,
queued: true,
onSuccess: (response) => {
const updateInfoList = JSON.parse(response);

if (updateInfo.version !== options.version) {
update('danger', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_UPDATEFOUND').replace('%s', `<span class="badge text-dark bg-light"> \u200E ${updateInfo.version}</span>`));
} else {
update('success', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_UPTODATE'));
}
}
if (Array.isArray(updateInfoList)) {
if (updateInfoList.length === 0) {
// No updates
update('success', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_UPTODATE'));
} else {
// An error occurred
update('danger', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_ERROR'));
const updateInfo = updateInfoList.shift();

if (updateInfo.version !== options.version) {
update('danger', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_UPDATEFOUND').replace('%s', `<span class="badge text-dark bg-light"> \u200E ${updateInfo.version}</span>`));
} else {
update('success', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_UPTODATE'));
}
}
})
.catch(() => {
// An error occurred
update('danger', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_ERROR'));
});
})
.catch(() => {
} else {
// An error occurred
update('danger', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_ERROR'));
}
},
onError: () => {
// An error occurred
update('danger', Joomla.Text._('PLG_QUICKICON_JOOMLAUPDATE_ERROR'));
});
},
});
};

// Give some times to the layout and other scripts to settle their stuff
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,17 @@
}
};

/**
* DO NOT use fetch() for QuickIcon requests. They must be queued.
*
* @see https://github.com/joomla/joomla-cms/issues/38001
*/
Joomla.request({
url: options.ajaxUrl,
method: 'GET',
data: '',
perform: true,
queued: true,
onSuccess: (response) => {
const updateInfoList = JSON.parse(response);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@
const quickicon = document.getElementById('plg_quickicon_privacycheck');
const link = quickicon.querySelector('span.j-links-link');

/**
* DO NOT use fetch() for QuickIcon requests. They must be queued.
*
* @see https://github.com/joomla/joomla-cms/issues/38001
*/
Joomla.request({
url: ajaxUrl,
method: 'GET',
data: '',
perform: true,
queued: true,
onSuccess: (response) => {
try {
const request = JSON.parse(response);
Expand Down
59 changes: 58 additions & 1 deletion build/media_source/system/js/core.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,27 @@ window.Joomla.Modal = window.Joomla.Modal || {
});
};

/**
* Joomla Request queue.
*
* A FIFO queue of requests to execute serially. Used to prevent simultaneous execution of
* multiple requests against the server which could trigger its Denial of Service protection.
*
* @type {Array}
*
* @since __DEPLOY_VERSION__
*/
const requestQueue = [];

/**
* Flag to indicate whether Joomla is performing a queued Request.
*
* @type {boolean}
*
* @since __DEPLOY_VERSION__
*/
let performingQueuedRequest = false;

/**
* Method to perform AJAX request
*
Expand All @@ -576,6 +597,8 @@ window.Joomla.Modal = window.Joomla.Modal || {
* https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/send
* perform: true, Perform the request immediately
* or return XMLHttpRequest instance and perform it later
* queued: false, Put the request in a FIFO queue; prevents simultaneous execution of
* multiple requests to avoid triggering the server's Denial of Service protection.
* headers: null, Object of custom headers, eg {'X-Foo': 'Bar', 'X-Bar': 'Foo'}
*
* onBefore: (xhr) => {} // Callback on before the request
Expand All @@ -598,13 +621,32 @@ window.Joomla.Modal = window.Joomla.Modal || {
* @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest
*/
Joomla.request = (options) => {
/**
* Processes queued Request objects.
*
* @since __DEPLOY_VERSION__
*/
const processQueuedRequests = () => {
if (performingQueuedRequest || requestQueue.length === 0) {
return;
}

performingQueuedRequest = true;

const nextRequest = requestQueue.shift();

nextRequest.xhr.send(nextRequest.data);
};

let xhr;

// Prepare the options
const newOptions = Joomla.extend({
url: '',
method: 'GET',
data: null,
perform: true,
queued: false,
}, options);

// Set up XMLHttpRequest instance
Expand Down Expand Up @@ -648,6 +690,12 @@ window.Joomla.Modal = window.Joomla.Modal || {
return;
}

// The request is finished; step through any more queued requests
if (newOptions.queued) {
performingQueuedRequest = false;
processQueuedRequests();
}

// Request finished and response is ready
if (xhr.status === 200) {
if (newOptions.onSuccess) {
Expand All @@ -663,14 +711,23 @@ window.Joomla.Modal = window.Joomla.Modal || {
};

// Do request
if (newOptions.perform) {
if (newOptions.perform && !newOptions.queued) {
if (newOptions.onBefore && newOptions.onBefore.call(window, xhr) === false) {
// Request interrupted
return xhr;
}

xhr.send(newOptions.data);
}

// Enqueue request and try to process the queue
if (newOptions.queued) {
requestQueue.push({
xhr,
data: newOptions.data,
});
processQueuedRequests();
}
} catch (error) {
// eslint-disable-next-line no-unused-expressions,no-console
window.console ? console.log(error) : null;
Expand Down

0 comments on commit d18db95

Please sign in to comment.