Commit 262fec95 authored by Oliver Hader's avatar Oliver Hader Committed by Benni Mack
Browse files

[TASK] Replace ResponseError with regular AjaxResponse

HTTP responses having a status code not in 200-299 are basically
still responses. In order to allow general response handling
ResponseError is dropped in favor of AjaxResponse.

Besides that `AjaxResponse.dereference()` has been introduced which
allows to forward relevant data (status, headers, body) in events or
broadcast messages to other `window` instances or frames.

Resolves: #92222
Releases: master, 10.4
Change-Id: I3ac986980fe53bb528046f58bc19392744122ee7
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65625


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Richard Haeser's avatarRichard Haeser <richard@richardhaeser.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Richard Haeser's avatarRichard Haeser <richard@richardhaeser.com>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent ef015d96
......@@ -13,7 +13,6 @@
import JQueryNativePromises from '../BackwardCompat/JQueryNativePromises';
import {AjaxResponse} from './AjaxResponse';
import {ResponseError} from './ResponseError';
import {GenericKeyValue, InputTransformer} from './InputTransformer';
class AjaxRequest {
......@@ -143,7 +142,7 @@ class AjaxRequest {
private async send(init: RequestInit = {}): Promise<Response> {
const response = await fetch(this.composeRequestUrl(), this.getMergedOptions(init));
if (!response.ok) {
throw new ResponseError(response);
throw new AjaxResponse(response);
}
return response;
}
......
......@@ -11,21 +11,47 @@
* The TYPO3 project - inspiring people to share!
*/
import SimpleResponseInterface from './SimpleResponseInterface';
export class AjaxResponse {
private readonly response: Response;
public readonly response: Response;
private resolvedBody: string | any;
constructor(response: Response) {
this.response = response;
}
public async resolve(): Promise<any> {
if (this.response.headers.has('Content-Type') && this.response.headers.get('Content-Type').includes('application/json')) {
return await this.response.json();
public async resolve(expectedType?: string): Promise<string | any> {
// streams can only be read once
// (otherwise response would have to be cloned)
if (typeof this.resolvedBody !== 'undefined') {
return this.resolvedBody;
}
const contentType: string = this.response.headers.get('Content-Type') ?? '';
if (expectedType === 'json' || contentType.startsWith('application/json')) {
this.resolvedBody = await this.response.json();
} else {
this.resolvedBody = await this.response.text();
}
return await this.response.text();
return this.resolvedBody;
}
public raw(): Response {
return this.response;
}
/**
* Dereferences response data from current `window` scope. A dereferenced
* response (`SimpleResponseInterface`) can be used in events or messages
* for broadcasting to other windows/frames.
*/
public async dereference(): Promise<SimpleResponseInterface> {
const headers = new Map<string, string>();
this.response.headers.forEach((value: string, name: string) => headers.set(name, value));
return {
status: this.response.status,
headers: headers,
body: await this.resolve()
} as SimpleResponseInterface;
}
}
......@@ -11,6 +11,9 @@
* The TYPO3 project - inspiring people to share!
*/
/**
* @deprecated Not used anymore
*/
export class ResponseError {
public readonly response: Response;
......
export default interface SimpleResponseInterface {
status: number;
headers: Map<string, string>;
body: string | any;
}
......@@ -11,7 +11,7 @@
* The TYPO3 project - inspiring people to share!
*/
import {ResponseError} from '../Ajax/ResponseError';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
/**
* Introduces a polyfill to support jQuery callbacks in native promises.
......@@ -27,7 +27,7 @@ export default class JQueryNativePromises {
if (typeof Promise.prototype.fail !== 'function') {
Promise.prototype.fail = function (onRejected: Function): Promise<any> {
this.catch(async (err: ResponseError): Promise<void> => {
this.catch(async (err: AjaxResponse): Promise<void> => {
const response = err.response;
onRejected(await JQueryNativePromises.createFakeXhrObject(response), 'error', response.statusText);
});
......
......@@ -15,7 +15,6 @@ import $ from 'jquery';
import NProgress from 'nprogress';
import Notification = require('TYPO3/CMS/Backend/Notification');
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest');
enum ExtensionManagerUpdateIdentifier {
......@@ -91,7 +90,7 @@ class ExtensionManagerUpdate {
reload = true;
window.location.replace(window.location.href);
}
}, async (error: ResponseError): Promise<void> => {
}, async (error: AjaxResponse): Promise<void> => {
// Create an error message with diagnosis info.
const errorMessage = error.response.statusText + '(' + error.response.status + '): ' + await error.response.text();
......
......@@ -14,7 +14,6 @@
import 'bootstrap';
import $ from 'jquery';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import Modal = require('TYPO3/CMS/Backend/Modal');
import Notification = require('TYPO3/CMS/Backend/Notification');
......@@ -86,7 +85,7 @@ class EnvironmentCheck extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -14,7 +14,6 @@
import 'bootstrap';
import $ from 'jquery';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import Modal = require('TYPO3/CMS/Backend/Modal');
import Notification = require('TYPO3/CMS/Backend/Notification');
......@@ -103,7 +102,7 @@ class FolderStructure extends AbstractInteractableModule {
InfoBox.render(element.severity, element.title, element.message),
);
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -139,7 +138,7 @@ class FolderStructure extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -14,7 +14,6 @@
import 'bootstrap';
import $ from 'jquery';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import Modal = require('TYPO3/CMS/Backend/Modal');
import Notification = require('TYPO3/CMS/Backend/Notification');
......@@ -59,7 +58,7 @@ class ImageProcessing extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -111,7 +110,7 @@ class ImageProcessing extends AbstractInteractableModule {
$container.append($aTwin);
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -13,7 +13,6 @@
import 'bootstrap';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import Modal = require('TYPO3/CMS/Backend/Modal');
import Notification = require('TYPO3/CMS/Backend/Notification');
......@@ -57,7 +56,7 @@ class MailTest extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
},
);
......
......@@ -15,7 +15,6 @@ import Notification = require('TYPO3/CMS/Backend/Notification');
import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest');
import Router = require('../../Router');
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
/**
......@@ -40,7 +39,7 @@ class PhpInfo extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -15,7 +15,6 @@ import Notification = require('TYPO3/CMS/Backend/Notification');
import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest');
import Router = require('../../Router');
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
/**
......@@ -40,7 +39,7 @@ class SystemInformation extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -13,7 +13,6 @@
import $ from 'jquery';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import Modal = require('TYPO3/CMS/Backend/Modal');
import Notification = require('TYPO3/CMS/Backend/Notification');
......@@ -78,7 +77,7 @@ class ClearTables extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -107,7 +106,7 @@ class ClearTables extends AbstractInteractableModule {
}
this.getStats();
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -13,7 +13,6 @@
import $ from 'jquery';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import Modal = require('TYPO3/CMS/Backend/Modal');
import Notification = require('TYPO3/CMS/Backend/Notification');
......@@ -77,7 +76,7 @@ class ClearTypo3tempFiles extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -107,7 +106,7 @@ class ClearTypo3tempFiles extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -17,7 +17,6 @@ import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest');
import Router = require('../../Router');
import PasswordStrength = require('../PasswordStrength');
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
/**
......@@ -54,7 +53,7 @@ class CreateAdmin extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
},
);
......@@ -87,7 +86,7 @@ class CreateAdmin extends AbstractInteractableModule {
} else {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
}, (error: ResponseError): void => {
}, (error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}).finally((): void => {
this.setModalButtonsState(true);
......
......@@ -13,7 +13,6 @@
import $ from 'jquery';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import Modal = require('TYPO3/CMS/Backend/Modal');
import Notification = require('TYPO3/CMS/Backend/Notification');
......@@ -68,7 +67,7 @@ class DatabaseAnalyzer extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -146,7 +145,7 @@ class DatabaseAnalyzer extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -183,7 +182,7 @@ class DatabaseAnalyzer extends AbstractInteractableModule {
}
this.analyze();
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -14,7 +14,6 @@
import 'bootstrap';
import $ from 'jquery';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest');
import SecurityUtility = require('TYPO3/CMS/Core/SecurityUtility');
......@@ -110,7 +109,7 @@ class LanguagePacks extends AbstractInteractableModule {
this.renderNotifications();
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -146,7 +145,7 @@ class LanguagePacks extends AbstractInteractableModule {
}
this.getData();
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -181,7 +180,7 @@ class LanguagePacks extends AbstractInteractableModule {
}
this.getData();
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -299,7 +298,7 @@ class LanguagePacks extends AbstractInteractableModule {
this.addNotification(m);
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -17,7 +17,6 @@ import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest');
import Router = require('../../Router');
import PasswordStrength = require('../PasswordStrength');
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
/**
......@@ -53,7 +52,7 @@ class ChangeInstallToolPassword extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -80,7 +79,7 @@ class ChangeInstallToolPassword extends AbstractInteractableModule {
} else {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
}, (error: ResponseError): void => {
}, (error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}).finally((): void => {
this.findInModal('.t3js-changeInstallToolPassword-password,.t3js-changeInstallToolPassword-password-check').val('');
......
......@@ -14,7 +14,6 @@
import 'bootstrap';
import $ from 'jquery';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import '../../Renderable/Clearable';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import ModuleMenu = require('TYPO3/CMS/Backend/ModuleMenu');
......@@ -86,7 +85,7 @@ class ExtensionConfiguration extends AbstractInteractableModule {
this.initializeWrap();
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -128,7 +127,7 @@ class ExtensionConfiguration extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
......@@ -13,7 +13,6 @@
import $ from 'jquery';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {ResponseError} from 'TYPO3/CMS/Core/Ajax/ResponseError';
import {AbstractInteractableModule} from '../AbstractInteractableModule';
import Modal = require('TYPO3/CMS/Backend/Modal');
import Notification = require('TYPO3/CMS/Backend/Notification');
......@@ -50,7 +49,7 @@ class Features extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......@@ -81,7 +80,7 @@ class Features extends AbstractInteractableModule {
Notification.error('Something went wrong', 'The request was not processed successfully. Please check the browser\'s console and TYPO3\'s log.');
}
},
(error: ResponseError): void => {
(error: AjaxResponse): void => {
Router.handleAjaxError(error, modalContent);
}
);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment