frest
Version:
REST client for browser with Fetch
103 lines (86 loc) • 2.72 kB
text/typescript
/**
* @module frest
* @hidden
*/
import { FrestRequest } from './types';
// These were taken from somewhere, made by someone.
// I adopted it to frest but forgot to put any reference to original source.
// If someone recognized these code and know where the original code came from,
// please raise an issue so that I can put attribution here.
const supportBlob = () =>
FileReader !== undefined &&
Blob !== undefined &&
(() => {
try {
// tslint:disable-next-line:no-unused-expression
new Blob();
return true;
} catch (error) {
return false;
}
})();
function parseHeaders(rawHeaders: any) {
const headers = new Headers();
// Replace instances of \r\n and \n followed by at least one space
// or horizontal tab with a space
// https://tools.ietf.org/html/rfc7230#section-3.2
const preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ');
preProcessedHeaders.split(/\r?\n/).forEach((line: any) => {
const parts = line.split(':');
const key = parts.shift().trim();
if (key) {
const value = parts.join(':').trim();
headers.append(key, value);
}
});
return headers;
}
function xhrFetch(url: string, conf: FrestRequest): Promise<Response> {
return new Promise<Response>((resolve, reject) => {
// const request = new Request(url, conf);
const xhr = new XMLHttpRequest();
xhr.onload = () => {
const options: any = {
headers: parseHeaders(xhr.getAllResponseHeaders() || ''),
status: xhr.status,
statusText: xhr.statusText,
};
options.url =
'responseURL' in xhr
? xhr.responseURL
: options.headers.get('X-Request-URL');
const body =
!conf.responseType || conf.responseType === 'text'
? xhr.responseText
: xhr.response;
resolve(new Response(body, options));
};
xhr.onerror = () => {
reject(new TypeError('Network request failed'));
};
xhr.ontimeout = () => {
reject(new TypeError('Network request failed'));
};
if (xhr.upload && conf.onUploadProgress) {
xhr.upload.onprogress = conf.onUploadProgress;
}
if (conf.onDownloadProgress) {
xhr.onprogress = conf.onDownloadProgress;
}
xhr.open(conf.method, url, true);
if (conf.credentials === 'include') {
xhr.withCredentials = true;
}
xhr.responseType = conf.responseType || 'text';
if (conf.action === 'download') {
if (!conf.responseType && supportBlob()) {
xhr.responseType = 'blob';
}
}
conf.headers.forEach((value, name) => {
xhr.setRequestHeader(name, value);
});
xhr.send(conf.body);
});
}
export default xhrFetch;