@jaricardodev/ews-javascript-api
Version:
EWS Managed api in JavaScript
197 lines (176 loc) • 6.18 kB
text/typescript
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;
}