Skip to content

Commit 6618c29

Browse files
committed
Merge branch 'code/fetch_options'
2 parents 2698a98 + b7b8111 commit 6618c29

File tree

6 files changed

+139
-22
lines changed

6 files changed

+139
-22
lines changed

Diff for: src/js/ConfigurationApi.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import { XHRFactory } from "./XHRFactory";
22
import { Promise, PromiseConstructor, ConfigurePromise } from "./Promise";
33
import { IXHROptions, IXHRApi } from "./Interfaces";
4+
import { FetchOptions } from 'fetch';
5+
import { XHRDefault } from './XHRDefault';
46

57
export class ConfigurationApi {
68

79
static ConfigureXHR(xhrApi: IXHRApi) {
810
XHRFactory.xhrHelper = xhrApi;
911
}
1012

13+
static SetXHROptions(fetchOptions: FetchOptions) {
14+
XHRDefault.defaultOptions = fetchOptions;
15+
}
16+
1117
static ConfigurePromise(promise: PromiseConstructor) {
1218
ConfigurePromise(promise);
1319
}
14-
}
20+
}

Diff for: src/js/ExchangeWebService.ts

+31
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,36 @@
33
* BootStrap code. to initializes some class to avoid circular reference.
44
*/
55

6+
/** polyfill */
7+
if (typeof Object.assign != 'function') {
8+
// Must be writable: true, enumerable: false, configurable: true
9+
Object.defineProperty(Object, "assign", {
10+
value: function assign(target, varArgs) { // .length of function is 2
11+
'use strict';
12+
if (target == null) { // TypeError if undefined or null
13+
throw new TypeError('Cannot convert undefined or null to object');
14+
}
15+
16+
var to = Object(target);
17+
18+
for (var index = 1; index < arguments.length; index++) {
19+
var nextSource = arguments[index];
20+
21+
if (nextSource != null) { // Skip over if undefined or null
22+
for (var nextKey in nextSource) {
23+
// Avoid bugs when hasOwnProperty is shadowed
24+
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
25+
to[nextKey] = nextSource[nextKey];
26+
}
27+
}
28+
}
29+
}
30+
return to;
31+
},
32+
writable: true,
33+
configurable: true
34+
});
35+
}
636

737
/** Promise type setup */
838
export { Promise } from "./Promise";
@@ -11,6 +41,7 @@ export { Promise } from "./Promise";
1141
export { IXHRApi, IXHROptions, IXHRProgress, } from "./Interfaces";
1242
export { ConfigurationApi } from "./ConfigurationApi";
1343
export { XHRFactory } from "./XHRFactory";
44+
export { XHRDefault } from "./XHRDefault";
1445

1546
/**Schema Bootstrapping */
1647
import { Schemas } from "./Core/ServiceObjects/Schemas/Schemas";

Diff for: src/js/XHRDefaults.ts renamed to src/js/XHRDefault.ts

+64-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
import { FetchStream, fetchUrl } from 'fetch';
1+
import { FetchStream, fetchUrl, FetchOptions } from 'fetch';
22
import { Promise } from "./Promise";
33
import { IXHROptions, IXHRApi, IXHRProgress } from "./Interfaces";
44

5-
/** @internal */
6-
export class XHRDefaults implements IXHRApi {
5+
/**
6+
* Default implementation of XHRApi using fetch
7+
*/
8+
export class XHRDefault implements IXHRApi {
79
static FetchStream: typeof FetchStream = FetchStream;
810
static fetchUrl: typeof fetchUrl = null;
11+
static defaultOptions: FetchOptions = {};
912

13+
fetchOptions: FetchOptions = {};
1014
private stream: FetchStream;
1115

1216
xhr(xhroptions: IXHROptions, progressDelegate?: (progressData: IXHRProgress) => void): Promise<XMLHttpRequest> {
13-
if (XHRDefaults.fetchUrl === null) {
17+
if (XHRDefault.fetchUrl === null) {
1418
throw new Error("xhrApi - stub method, must be bootstrapped");
1519
}
1620
//setup xhr for github.com/andris9/fetch options
@@ -26,7 +30,7 @@ export class XHRDefaults implements IXHRApi {
2630
// delete xhroptions["type"];
2731

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

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

@@ -68,7 +72,7 @@ export class XHRDefaults implements IXHRApi {
6872
}
6973

7074
return new Promise((resolve, reject) => {
71-
this.stream = new XHRDefaults.FetchStream(xhroptions.url, options);
75+
this.stream = new XHRDefault.FetchStream(xhroptions.url, this.getOptions(options));
7276

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

108-
constructor() {
112+
constructor(fetchOptions: FetchOptions = {}) {
113+
this.fetchOptions = fetchOptions;
109114
try {
110115
let fetch = require("fetch");
111-
XHRDefaults.FetchStream = fetch.FetchStream;
112-
XHRDefaults.fetchUrl = fetch.fetchUrl;
116+
XHRDefault.FetchStream = fetch.FetchStream;
117+
XHRDefault.fetchUrl = fetch.fetchUrl;
113118
}
114119
catch (e) { }
115120
}
121+
122+
private getOptions(opts: FetchOptions) {
123+
let headers = Object.assign({}, (XHRDefault.defaultOptions || {}).headers, (this.fetchOptions || {}).headers, (opts || {}).headers)
124+
return Object.assign({}, XHRDefault.defaultOptions, this.fetchOptions, opts, { headers });
125+
}
116126
}
117127

118128
/** @internal */
@@ -144,4 +154,47 @@ function setupXhrResponse(xhrResponse: XMLHttpRequest): XMLHttpRequest {
144154
}
145155

146156
return xhrResponse;
147-
}
157+
}
158+
159+
export interface xFetchOptions {
160+
/** how many redirects allowed, defaults to 10 */
161+
maxRedirects: number;
162+
/** set to true if redirects are not allowed, defaults to false */
163+
disableRedirects: boolean;
164+
/** optional header fields, in the form of {'Header-Field':'value'} */
165+
headers: { [key: string]: (any) };
166+
/** maximum allowd length for the file, the remainder is cut off. Defaults to Infinity */
167+
maxResponseLength: number;
168+
/** defaults to GET */
169+
method: string;
170+
/** request body */
171+
payload: string;
172+
/** set to false, to disable content gzipping, needed for Node v0.5.9 which has buggy zlib */
173+
disableGzip: boolean;
174+
/** an array of cookie definitions in the form of ['name=val'] */
175+
cookies: any;
176+
/** for sharing cookies between requests, see below */
177+
cookieJar: any;
178+
/** valid for fetchUrl */
179+
outputEncoding: string;
180+
/** valid for fetchUrl, set to true to disable automatic charset decoding to utf-8 */
181+
disableDecoding: boolean;
182+
/** valid for fetchUrl, set input encoding */
183+
overrideCharset: string;
184+
/** use high performance asyncronous DNS resolution based on c-ares instead of a thread pool calling getaddrinfo(3) */
185+
asyncDnsLoookup: boolean;
186+
/** set a timeout in ms */
187+
timeout: number;
188+
/** pass-through http.request agent parameter for https */
189+
agentHttps: any;
190+
/** pass-through http.request agent parameter for http */
191+
agentHttp: any;
192+
/** pass-through http.request agent parameter as fallback, if agentHttps or agentHttp are not specified */
193+
agent: any;
194+
/** whether to reject self-signed certificates (true, default behavior), or ignore and allow them (false) */
195+
rejectUnauthorized: boolean;
196+
/** is the username for Basic auth */
197+
user: string;
198+
/** is the password for Basic auth */
199+
pass: string;
200+
}

Diff for: src/js/XHRFactory.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import { Promise } from "./Promise";
22
import { IXHROptions, IXHRApi } from "./Interfaces";
3-
import { XHRDefaults } from "./XHRDefaults"
3+
import { XHRDefault } from "./XHRDefault"
44

55
export class XHRFactory {
66

77
static xhrHelper: IXHRApi;
88
static get XHRApi() {
99
if (typeof this.xhrHelper === 'undefined' || this.xhrHelper === null) {
10-
this.xhrHelper = new XHRDefaults();
10+
this.xhrHelper = new XHRDefault();
1111
}
1212
return this.xhrHelper;
1313
}
1414

1515
public static newXHRApi() {
16-
return new XHRDefaults();
16+
console.warn("depricated, import and use \"new XHRDefault(options?)\" instead")
17+
return new XHRDefault();
1718
}
1819
}

Diff for: tsconfig.json

+7-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
"allowUnreachableCode": true,
1313
"pretty": false,
1414
"inlineSourceMap": false,
15-
"stripInternal": true
15+
"stripInternal": true,
16+
"lib": [
17+
"es2015",
18+
"dom"
19+
]
1620
},
1721
"compileOnSave": false,
1822
"exclude": [
@@ -22,5 +26,5 @@
2226
"src/js/System.d.ts",
2327
"typings/ExchangeWebService.d.ts",
2428
"src/js/Microsoft.Exchange.WebServices.d__.ts"
25-
]
26-
}
29+
]
30+
}

Diff for: typings/fetch.d.ts

+26-4
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,55 @@ declare module 'fetch' {
77
cookieJar: any
88
}
99

10-
export interface fetchOptions {
10+
export interface FetchOptions {
11+
/** how many redirects allowed, defaults to 10 */
1112
maxRedirects?: number;
13+
/** set to true if redirects are not allowed, defaults to false */
1214
disableRedirects?: boolean;
13-
headers?: any;
15+
/** optional header fields, in the form of {'Header-Field':'value'} */
16+
headers?: { [key: string]: (any) };
17+
/** maximum allowd length for the file, the remainder is cut off. Defaults to Infinity */
1418
maxResponseLength?: number | "infinity";
19+
/** defaults to GET */
1520
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS';
21+
/** request body */
1622
payload?: string;
23+
/** set to false, to disable content gzipping, needed for Node v0.5.9 which has buggy zlib */
1724
disableGzip?: boolean;
25+
/** an array of cookie definitions in the form of ['name=val'] */
1826
cookies?: any;
27+
/** for sharing cookies between requests, see below */
1928
cookieJar?: any;
29+
/** valid for fetchUrl */
2030
outputEncoding?: any;
31+
/** valid for fetchUrl, set to true to disable automatic charset decoding to utf-8 */
2132
disableDecoding?: any;
33+
/** valid for fetchUrl, set input encoding */
2234
overrideCharset?: any;
35+
/** use high performance asyncronous DNS resolution based on c-ares instead of a thread pool calling getaddrinfo(3) */
2336
asyncDnsLoookup?: any;
37+
/** set a timeout in ms */
2438
timeout?: number;
39+
/** pass-through http.request agent parameter for https */
2540
agentHttps?: any;
41+
/** pass-through http.request agent parameter for http */
2642
agentHttp?: any;
43+
/** pass-through http.request agent parameter as fallback, if agentHttps or agentHttp are not specified */
2744
agent?: any;
45+
/** whether to reject self-signed certificates (true, default behavior), or ignore and allow them (false) */
2846
rejectUnauthorized?: boolean;
47+
/** is the username for Basic auth */
48+
user?: string;
49+
/** is the password for Basic auth */
50+
pass?: string;
2951
}
3052

3153
export class FetchStream {
32-
constructor(url: string, options: fetchOptions);
54+
constructor(url: string, options: FetchOptions);
3355
destroy(): void;
3456
on: (event: 'data' | 'meta' | 'end' | 'error', callback?: (data?: string) => void) => void;
3557
}
3658

3759
export function fetchUrl(url: string, callback: (error: Error, meta: Meta, body: string) => void): void;
38-
export function fetchUrl(url: string, options: fetchOptions, callback: (error: Error, meta: Meta, body: string) => void): void;
60+
export function fetchUrl(url: string, options: FetchOptions, callback: (error: Error, meta: Meta, body: string) => void): void;
3961
}

0 commit comments

Comments
 (0)