replace jQuery.ajax with fetch (or XMLHttpRequest for synchronous requests)

This commit is contained in:
Ralf Becker 2021-07-16 08:47:22 +02:00
parent 2f155e0d79
commit b780c7ebd8
2 changed files with 88 additions and 44 deletions

View File

@ -47,25 +47,33 @@ export function et2_loadXMLFromURL(_url : string, _callback? : Function, _contex
{ {
win = egw.top; win = egw.top;
} }
return win.jQuery.ajax({
// we add the full url (protocol and domain) as sometimes just the path // we add the full url (protocol and domain) as sometimes just the path
// gives a CSP error interpreting it as file:///path // gives a CSP error interpreting it as file:///path
// (if there are a enough 404 errors in html content ...) // (if there are a enough 404 errors in html content ...)
url: (_url[0]=='/' ? location.protocol+'//'+location.host : '')+_url, return win.fetch((_url[0] === '/' ? location.protocol+'//'+location.host : '')+_url, {
context: _context, method: 'GET'
type: 'GET', })
dataType: 'xml', .then((response) => {
success: function(_data, _status, _xmlhttp){ if (!response.ok) {
if (typeof _callback === 'function') { throw response;
_callback.call(_context, _data.documentElement);
} }
}, return response.text();
error: function(_xmlhttp, _err) { })
egw().debug('error', 'Loading eTemplate from '+_url+' failed! '+_xmlhttp.status+' '+_xmlhttp.statusText); .then((xml) => {
const parser = new window.DOMParser();
return parser.parseFromString( xml, "text/xml" );
})
.then((xmldoc) => {
if (typeof _callback === 'function') {
_callback.call(_context, xmldoc.children[0]);
}
return xmldoc.children[0];
})
.catch((_err) => {
egw().debug('error', 'Loading eTemplate from '+_url+' failed! '+_err.status+' '+_err.statusText);
if(typeof _fail_callback === 'function') { if(typeof _fail_callback === 'function') {
_fail_callback.call(_context, _err); _fail_callback.call(_context, _err);
} }
}
}); });
} }

View File

@ -203,7 +203,7 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
if (typeof method === 'undefined') method = 'POST'; if (typeof method === 'undefined') method = 'POST';
// Assemble the complete request // Assemble the complete request
var request_obj = JSON.stringify({ const request_obj = JSON.stringify({
request: { request: {
parameters: this.parameters parameters: this.parameters
} }
@ -218,53 +218,89 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
return navigator.sendBeacon(this.url, data); return navigator.sendBeacon(this.url, data);
} }
// Send the request via AJAX using the jquery ajax function let url = this.url;
// we need to use jQuery of window of egw object, as otherwise the one from main window is used! let init = {
// (causing eg. apply from server with app.$app.method to run in main window instead of popup) method: method
this.request = (this.egw.window?this.egw.window.jQuery:jQuery).ajax({ }
url: this.url, if (method === 'GET')
async: this.async, {
context: this, url += (url.indexOf('?') === -1 ? '?' : '&') + new URLSearchParams({ json_data: request_obj });
// only POST can send JSON as direct payload, GET can not }
data: method === 'GET' ? { json_data: request_obj } : request_obj, else
contentType: method === 'GET' ? false : 'application/json', {
dataType: 'json', init.headers = { 'Content-Type': 'application/json'};
type: method, init.body = request_obj;
success: this.handleResponse, }
jsonp: false, if (this.async)
error: error || this.handleError {
this.request = (this.egw.window?this.egw.window:window).fetch(url, init)
.then((response) => {
if (!response.ok) {
throw response;
}
return response.json();
})
.then((data) => this.handleResponse(data))
.catch((_err) => {
(error || this.handleError).call(this, _err)
}); });
}
else
{
console.trace("Synchronous AJAX request detected", this);
this.request = new XMLHttpRequest();
this.request.open(method, url, false);
if (method !== 'GET') this.request.setRequestHeader('Content-Type', 'application/json');
this.request.send(init.body);
if (this.request.status !== 200)
{
(error || this.handleError).call(this, this.request, 'error')
}
else
{
this.handleResponse(JSON.parse(this.request.responseText));
}
}
return this.request; return this.request;
}; };
/** /**
* Default error callback displaying error via egw.message * Default error callback displaying error via egw.message
* *
* @param {XMLHTTP} _xmlhttp * @param {XMLHTTP|Response} response
* @param {string} _err * @param {string} _err
*/ */
json_request.prototype.handleError = function(_xmlhttp, _err) { json_request.prototype.handleError = function(response, _err) {
// Don't error about an abort // Don't error about an abort
if(_err !== 'abort') if(_err !== 'abort')
{ {
// for fetch Response get json, as it's used below
if (typeof response.headers === 'object' && response.headers.get('Content-Type') === 'application/json')
{
return response.json().then((json) => {
response.responseJSON = json;
this.handleError(response, 'error');
})
}
const date = typeof response.headers === 'object' ? 'Date: '+response.headers.get('Date') :
response.getAllResponseHeaders().match(/^Date:.*$/mi)[0] ||
'Date: '+(new Date).toString();
this.egw.message.call(this.egw, this.egw.message.call(this.egw,
this.egw.lang('A request to the EGroupware server returned with an error')+ this.egw.lang('A request to the EGroupware server returned with an error')+
': '+_xmlhttp.statusText+' ('+_xmlhttp.status+")\n\n"+ ': '+response.statusText+' ('+response.status+")\n\n"+
this.egw.lang('Please reload the EGroupware desktop (F5 / Cmd+r).')+"\n"+ this.egw.lang('Please reload the EGroupware desktop (F5 / Cmd+r).')+"\n"+
this.egw.lang('If the error persists, contact your administrator for help and ask to check the error-log of the webserver.')+ this.egw.lang('If the error persists, contact your administrator for help and ask to check the error-log of the webserver.')+
"\n\nURL: "+this.url+"\n"+ "\n\nURL: "+this.url+"\n"+date+
(_xmlhttp.getAllResponseHeaders() ? (_xmlhttp.getAllResponseHeaders().match(/^Date:.*$/mi) ? _xmlhttp.getAllResponseHeaders().match(/^Date:.*$/mi)[0]:''):'')+
// if EGroupware send JSON payload with error, errno show it here too // if EGroupware send JSON payload with error, errno show it here too
(_err === 'error' && _xmlhttp.status === 400 && typeof _xmlhttp.responseJSON === 'object' && _xmlhttp.responseJSON.error ? (_err === 'error' && response.status === 400 && typeof response.responseJSON === 'object' && response.responseJSON.error ?
"\nError: "+_xmlhttp.responseJSON.error+' ('+_xmlhttp.responseJSON.errno+')' : '') "\nError: "+response.responseJSON.error+' ('+response.responseJSON.errno+')' : '')
); );
this.egw.debug('error', 'Ajax request to', this.url, ' failed: ', _err, _xmlhttp.status, _xmlhttp.statusText, _xmlhttp.responseJSON); this.egw.debug('error', 'Ajax request to', this.url, ' failed: ', _err, response.status, response.statusText, response.responseJSON);
// check of unparsable JSON on server-side, which might be caused by some network problem --> resend max. twice // check of unparsable JSON on server-side, which might be caused by some network problem --> resend max. twice
if (_err === 'error' && _xmlhttp.status === 400 && typeof _xmlhttp.responseJSON === 'object' && if (_err === 'error' && response.status === 400 && typeof response.responseJSON === 'object' &&
_xmlhttp.responseJSON.errno && _xmlhttp.responseJSON.error.substr(0, 5) === 'JSON ') response.responseJSON.errno && response.responseJSON.error.substr(0, 5) === 'JSON ')
{ {
// ToDo: resend request max. twice // ToDo: resend request max. twice
} }