UNPKG

@jaricardodev/ews-javascript-api

Version:
197 lines (176 loc) 6.18 kB
import { FetchStream, fetchUrl, FetchOptions } from 'fetch'; import { IXHROptions, IXHRApi, IXHRProgress } from "./Interfaces"; /** * Default implementation of XHRApi using fetch */ export class XHRDefault implements IXHRApi { static FetchStream: typeof FetchStream = FetchStream; static fetchUrl: typeof fetchUrl = null; static defaultOptions: FetchOptions = {}; fetchOptions: FetchOptions = {}; private stream: FetchStream; xhr(xhroptions: IXHROptions, progressDelegate?: (progressData: IXHRProgress) => void): Promise<XMLHttpRequest> { if (XHRDefault.fetchUrl === null) { throw new Error("xhrApi - stub method, must be bootstrapped"); } //setup xhr for github.com/andris9/fetch options let options = { url: xhroptions.url, payload: xhroptions.data, headers: xhroptions.headers, method: <any>xhroptions.type, disableRedirects: !xhroptions.allowRedirect, } return new Promise<XMLHttpRequest>((resolve, reject) => { XHRDefault.fetchUrl(xhroptions.url, this.getOptions(options), (error, meta, body) => { if (error) { if (typeof (<any>error).status === 'undefined') { (<any>error).status = 0; } reject(setupXhrResponse(<any>error)); } else { let xhrResponse: XMLHttpRequest = <any>{ response: body.toString(), status: meta.status, redirectCount: meta.redirectCount, headers: meta.responseHeaders, finalUrl: meta.finalUrl, responseType: '', statusText: undefined, }; if (xhrResponse.status === 200) { resolve(setupXhrResponse(xhrResponse)); } else { reject(setupXhrResponse(xhrResponse)); } } }); }) } xhrStream(xhroptions: IXHROptions, progressDelegate: (progressData: IXHRProgress) => void): Promise<XMLHttpRequest> { if (XHRDefault.FetchStream === null) { throw new Error("xhrApi - stub method, must be bootstrapped"); } //setup xhr for github.com/andris9/fetch options let options = { payload: xhroptions.data, headers: xhroptions.headers, method: <any>xhroptions.type } return new Promise((resolve, reject) => { this.stream = new XHRDefault.FetchStream(xhroptions.url, this.getOptions(options)); this.stream.on("data", (chunk) => { //console.log(chunk.toString()); progressDelegate({ type: "data", data: chunk.toString() }); }); this.stream.on("meta", (meta) => { progressDelegate({ type: "header", headers: meta["responseHeaders"] }); }); this.stream.on("end", () => { progressDelegate({ type: "end" }); resolve(void 0); }); this.stream.on('error', (error) => { progressDelegate({ type: "error", error: error }); this.disconnect(); reject(error); }); }); } disconnect() { if (this.stream) { try { this.stream.destroy(); } catch (e) { } } } get apiName(): string { return "default"; } constructor(fetchOptions: FetchOptions = {}) { this.fetchOptions = fetchOptions; try { let fetch = require("fetch"); XHRDefault.FetchStream = fetch.FetchStream; XHRDefault.fetchUrl = fetch.fetchUrl; } catch (e) { } } private getOptions(opts: FetchOptions) { let headers = Object.assign({}, (XHRDefault.defaultOptions || {}).headers, (this.fetchOptions || {}).headers, (opts || {}).headers) return Object.assign({}, XHRDefault.defaultOptions, this.fetchOptions, opts, { headers }); } } /** @internal */ function setupXhrResponse(xhrResponse: XMLHttpRequest): XMLHttpRequest { xhrResponse[<any>"responseText"] = xhrResponse.response; delete xhrResponse[<any>"response"]; xhrResponse.getAllResponseHeaders = function () { var header = ""; if ((<any>xhrResponse).headers) { for (var key in (<any>xhrResponse).headers) { header += key + " : " + (<any>xhrResponse).headers[key] + "\r\n"; } } return header; }; xhrResponse.getResponseHeader = (header: string) => { if (header) { if ((<any>xhrResponse).headers) { if ((<any>xhrResponse).headers[header]) { return (<any>xhrResponse).headers[header]; } if ((<any>xhrResponse).headers[header.toLocaleLowerCase()]) { return (<any>xhrResponse).headers[header.toLocaleLowerCase()]; } } } return null; } return xhrResponse; } export interface xFetchOptions { /** how many redirects allowed, defaults to 10 */ maxRedirects: number; /** set to true if redirects are not allowed, defaults to false */ disableRedirects: boolean; /** optional header fields, in the form of {'Header-Field':'value'} */ headers: { [key: string]: (any) }; /** maximum allowd length for the file, the remainder is cut off. Defaults to Infinity */ maxResponseLength: number; /** defaults to GET */ method: string; /** request body */ payload: string; /** set to false, to disable content gzipping, needed for Node v0.5.9 which has buggy zlib */ disableGzip: boolean; /** an array of cookie definitions in the form of ['name=val'] */ cookies: any; /** for sharing cookies between requests, see below */ cookieJar: any; /** valid for fetchUrl */ outputEncoding: string; /** valid for fetchUrl, set to true to disable automatic charset decoding to utf-8 */ disableDecoding: boolean; /** valid for fetchUrl, set input encoding */ overrideCharset: string; /** use high performance asyncronous DNS resolution based on c-ares instead of a thread pool calling getaddrinfo(3) */ asyncDnsLoookup: boolean; /** set a timeout in ms */ timeout: number; /** pass-through http.request agent parameter for https */ agentHttps: any; /** pass-through http.request agent parameter for http */ agentHttp: any; /** pass-through http.request agent parameter as fallback, if agentHttps or agentHttp are not specified */ agent: any; /** whether to reject self-signed certificates (true, default behavior), or ignore and allow them (false) */ rejectUnauthorized: boolean; /** is the username for Basic auth */ user: string; /** is the password for Basic auth */ pass: string; }