import { Future, Optional } from '@ephox/katamari'; import { readBlobAsText } from './BlobReader'; import { DataType } from './DataType'; import type { ResponseBodyDataTypes, ResponseType } from './HttpData'; import type { HttpError } from './HttpError'; import * as JsonResponse from './JsonResponse'; // can't get responseText of a blob, throws a DomException. Need to use FileReader. // request.response can be null if the server provided no content in the error response. const getBlobError = (request: XMLHttpRequest) => Optional.from(request.response).map(readBlobAsText).getOr(Future.pure('no response content')); const fallback = (request: XMLHttpRequest) => Future.pure(request.response); const getResponseText = (responseType: ResponseBodyDataTypes, request: XMLHttpRequest) => { // for errors, the responseText is json if it can be, fallback if it can't switch (responseType) { case DataType.JSON: return JsonResponse.create(request.response).fold(() => fallback(request), Future.pure); case DataType.Blob: return getBlobError(request); case DataType.Text: return fallback(request); default: return fallback(request); } }; const statusText = (request: XMLHttpRequest): string => { if (request.statusText === '') { // Safari bug with HTTPS requests if (request.status === 404) { return 'Not Found'; } else { return `Response code ${request.status}`; } } else { return request.statusText; } }; const errorMessage = (url: string, request: XMLHttpRequest): string => { if (request.status === 0) { return 'Unknown HTTP error (possible cross-domain request)'; } else { return `Could not load url ${url}: ${statusText(request)}`; } }; export const handle = (url: string, responseType: ResponseBodyDataTypes, request: XMLHttpRequest): Future> => getResponseText(responseType, request).map((responseText) => { return { message: errorMessage(url, request), status: request.status, responseText }; });