Skip to content

Commit

Permalink
Merge branch 'code/fetch_options'
Browse files Browse the repository at this point in the history
  • Loading branch information
gautamsi committed Mar 23, 2018
2 parents 2698a98 + b7b8111 commit 6618c29
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 22 deletions.
8 changes: 7 additions & 1 deletion src/js/ConfigurationApi.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { XHRFactory } from "./XHRFactory";
import { Promise, PromiseConstructor, ConfigurePromise } from "./Promise";
import { IXHROptions, IXHRApi } from "./Interfaces";
import { FetchOptions } from 'fetch';
import { XHRDefault } from './XHRDefault';

export class ConfigurationApi {

static ConfigureXHR(xhrApi: IXHRApi) {
XHRFactory.xhrHelper = xhrApi;
}

static SetXHROptions(fetchOptions: FetchOptions) {
XHRDefault.defaultOptions = fetchOptions;
}

static ConfigurePromise(promise: PromiseConstructor) {
ConfigurePromise(promise);
}
}
}
31 changes: 31 additions & 0 deletions src/js/ExchangeWebService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,36 @@
* BootStrap code. to initializes some class to avoid circular reference.
*/

/** polyfill */
if (typeof Object.assign != 'function') {
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, "assign", {
value: function assign(target, varArgs) { // .length of function is 2
'use strict';
if (target == null) { // TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
}

var to = Object(target);

for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];

if (nextSource != null) { // Skip over if undefined or null
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
},
writable: true,
configurable: true
});
}

/** Promise type setup */
export { Promise } from "./Promise";
Expand All @@ -11,6 +41,7 @@ export { Promise } from "./Promise";
export { IXHRApi, IXHROptions, IXHRProgress, } from "./Interfaces";
export { ConfigurationApi } from "./ConfigurationApi";
export { XHRFactory } from "./XHRFactory";
export { XHRDefault } from "./XHRDefault";

/**Schema Bootstrapping */
import { Schemas } from "./Core/ServiceObjects/Schemas/Schemas";
Expand Down
75 changes: 64 additions & 11 deletions src/js/XHRDefaults.ts → src/js/XHRDefault.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { FetchStream, fetchUrl } from 'fetch';
import { FetchStream, fetchUrl, FetchOptions } from 'fetch';
import { Promise } from "./Promise";
import { IXHROptions, IXHRApi, IXHRProgress } from "./Interfaces";

/** @internal */
export class XHRDefaults implements IXHRApi {
/**
* 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 (XHRDefaults.fetchUrl === null) {
if (XHRDefault.fetchUrl === null) {
throw new Error("xhrApi - stub method, must be bootstrapped");
}
//setup xhr for github.com/andris9/fetch options
Expand All @@ -26,7 +30,7 @@ export class XHRDefaults implements IXHRApi {
// delete xhroptions["type"];

return new Promise<XMLHttpRequest>((resolve, reject) => {
XHRDefaults.fetchUrl(xhroptions.url, options, (error, meta, body) => {
XHRDefault.fetchUrl(xhroptions.url, this.getOptions(options), (error, meta, body) => {
if (error) {
if (typeof (<any>error).status === 'undefined') {
(<any>error).status = 0;
Expand Down Expand Up @@ -56,7 +60,7 @@ export class XHRDefaults implements IXHRApi {
}

xhrStream(xhroptions: IXHROptions, progressDelegate: (progressData: IXHRProgress) => void): Promise<XMLHttpRequest> {
if (XHRDefaults.FetchStream === null) {
if (XHRDefault.FetchStream === null) {
throw new Error("xhrApi - stub method, must be bootstrapped");
}

Expand All @@ -68,7 +72,7 @@ export class XHRDefaults implements IXHRApi {
}

return new Promise((resolve, reject) => {
this.stream = new XHRDefaults.FetchStream(xhroptions.url, options);
this.stream = new XHRDefault.FetchStream(xhroptions.url, this.getOptions(options));

this.stream.on("data", (chunk) => {
//console.log(chunk.toString());
Expand Down Expand Up @@ -105,14 +109,20 @@ export class XHRDefaults implements IXHRApi {
return "default";
}

constructor() {
constructor(fetchOptions: FetchOptions = {}) {
this.fetchOptions = fetchOptions;
try {
let fetch = require("fetch");
XHRDefaults.FetchStream = fetch.FetchStream;
XHRDefaults.fetchUrl = fetch.fetchUrl;
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 */
Expand Down Expand Up @@ -144,4 +154,47 @@ function setupXhrResponse(xhrResponse: XMLHttpRequest): XMLHttpRequest {
}

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;
}
7 changes: 4 additions & 3 deletions src/js/XHRFactory.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { Promise } from "./Promise";
import { IXHROptions, IXHRApi } from "./Interfaces";
import { XHRDefaults } from "./XHRDefaults"
import { XHRDefault } from "./XHRDefault"

export class XHRFactory {

static xhrHelper: IXHRApi;
static get XHRApi() {
if (typeof this.xhrHelper === 'undefined' || this.xhrHelper === null) {
this.xhrHelper = new XHRDefaults();
this.xhrHelper = new XHRDefault();
}
return this.xhrHelper;
}

public static newXHRApi() {
return new XHRDefaults();
console.warn("depricated, import and use \"new XHRDefault(options?)\" instead")
return new XHRDefault();
}
}
10 changes: 7 additions & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
"allowUnreachableCode": true,
"pretty": false,
"inlineSourceMap": false,
"stripInternal": true
"stripInternal": true,
"lib": [
"es2015",
"dom"
]
},
"compileOnSave": false,
"exclude": [
Expand All @@ -22,5 +26,5 @@
"src/js/System.d.ts",
"typings/ExchangeWebService.d.ts",
"src/js/Microsoft.Exchange.WebServices.d__.ts"
]
}
]
}
30 changes: 26 additions & 4 deletions typings/fetch.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,55 @@ declare module 'fetch' {
cookieJar: any
}

export interface fetchOptions {
export interface FetchOptions {
/** how many redirects allowed, defaults to 10 */
maxRedirects?: number;
/** set to true if redirects are not allowed, defaults to false */
disableRedirects?: boolean;
headers?: any;
/** 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 | "infinity";
/** defaults to GET */
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS';
/** 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?: any;
/** valid for fetchUrl, set to true to disable automatic charset decoding to utf-8 */
disableDecoding?: any;
/** valid for fetchUrl, set input encoding */
overrideCharset?: any;
/** use high performance asyncronous DNS resolution based on c-ares instead of a thread pool calling getaddrinfo(3) */
asyncDnsLoookup?: any;
/** 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;
}

export class FetchStream {
constructor(url: string, options: fetchOptions);
constructor(url: string, options: FetchOptions);
destroy(): void;
on: (event: 'data' | 'meta' | 'end' | 'error', callback?: (data?: string) => void) => void;
}

export function fetchUrl(url: string, callback: (error: Error, meta: Meta, body: string) => void): void;
export function fetchUrl(url: string, options: fetchOptions, callback: (error: Error, meta: Meta, body: string) => void): void;
export function fetchUrl(url: string, options: FetchOptions, callback: (error: Error, meta: Meta, body: string) => void): void;
}

0 comments on commit 6618c29

Please sign in to comment.