Skip to content

Commit de8a55b

Browse files
authored
Merge pull request #239 from microsoftgraph/build_middleware_chain
Simplify building middleware chain
2 parents 7baaf98 + b2f7d3b commit de8a55b

8 files changed

+126
-0
lines changed

spec/core/HTTPClient.ts

+39
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77

88
import { assert } from "chai";
99

10+
import { Client } from "../../src/Client";
1011
import { HTTPClient } from "../../src/HTTPClient";
1112
import { Context } from "../../src/IContext";
1213
import { FetchOptions } from "../../src/IFetchOptions";
14+
import { RedirectHandlerOptions } from "../../src/middleware/options/RedirectHandlerOptions";
15+
import { RedirectHandler } from "../../src/middleware/RedirectHandler";
16+
import { TelemetryHandler } from "../../src/middleware/TelemetryHandler";
1317
import { DummyHTTPMessageHandler } from "../DummyHTTPMessageHandler";
1418

1519
describe("HTTPClient.ts", () => {
@@ -68,4 +72,39 @@ describe("HTTPClient.ts", () => {
6872
}
6973
});
7074
});
75+
76+
describe("getMiddlewareArray", () => {
77+
it("Should work fine for a single middleware in the chain, which does have a getNext method", () => {
78+
const telemetryHandler = new TelemetryHandler();
79+
const tempHttpClient: HTTPClient = new HTTPClient(telemetryHandler);
80+
assert.equal(tempHttpClient.getMiddlewareArray().length, 1);
81+
});
82+
83+
it("Should work fine for a single middleware in the chain, which doesn't have a getNext method", () => {
84+
const tempHttpClient: HTTPClient = new HTTPClient(httpMessageHandler);
85+
assert.equal(tempHttpClient.getMiddlewareArray().length, 1);
86+
});
87+
88+
it("Should work fine for a chain containing many middlewares", () => {
89+
const telemetryHandler = new TelemetryHandler();
90+
const redirectHandler = new RedirectHandler(new RedirectHandlerOptions());
91+
redirectHandler.setNext(telemetryHandler);
92+
telemetryHandler.setNext(httpMessageHandler);
93+
const tempHttpClient: HTTPClient = new HTTPClient(redirectHandler);
94+
assert.equal(tempHttpClient.getMiddlewareArray().length, 3);
95+
});
96+
});
97+
98+
describe("setMiddlewareArray", () => {
99+
it("Should make a chain out of the provided array of middlewares", () => {
100+
const telemetryHandler = new TelemetryHandler();
101+
const redirectHandler = new RedirectHandler(new RedirectHandlerOptions());
102+
redirectHandler.setNext(httpMessageHandler);
103+
const tempHttpClient: HTTPClient = new HTTPClient(redirectHandler);
104+
const middlewareArray = tempHttpClient.getMiddlewareArray();
105+
middlewareArray.splice(1, 0, telemetryHandler);
106+
tempHttpClient.setMiddlewareArray(middlewareArray);
107+
assert.equal(tempHttpClient.getMiddlewareArray().length, 3);
108+
});
109+
});
71110
});

src/Client.ts

+19
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { HTTPClient } from "./HTTPClient";
1616
import { HTTPClientFactory } from "./HTTPClientFactory";
1717
import { ClientOptions } from "./IClientOptions";
1818
import { Options } from "./IOptions";
19+
import { Middleware } from "./middleware/IMiddleware";
1920
import { validatePolyFilling } from "./ValidatePolyFilling";
2021

2122
export class Client {
@@ -103,6 +104,24 @@ export class Client {
103104
this.httpClient = httpClient;
104105
}
105106

107+
/**
108+
* @public
109+
* function to get the array of middlewares in use right now
110+
* @returns An array of middlewares
111+
*/
112+
public getMiddlewareChain() {
113+
return this.httpClient.getMiddlewareArray();
114+
}
115+
116+
/**
117+
* @public
118+
* function to set the middleware chain
119+
* @param {Middleware[]} middlewareArray - An array of middlewares
120+
*/
121+
public setMiddlewareChain(middlewareArray: Middleware[]) {
122+
return this.httpClient.setMiddlewareArray(middlewareArray);
123+
}
124+
106125
/**
107126
* @public
108127
* Entry point to make requests

src/HTTPClient.ts

+31
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,37 @@ export class HTTPClient {
3333
this.middleware = middleware;
3434
}
3535

36+
/**
37+
* @public
38+
* To get an array of Middleware, used in middleware chain
39+
* @returns An array of middlewares
40+
*/
41+
public getMiddlewareArray(): Middleware[] {
42+
const middlewareArray: Middleware[] = [];
43+
let currentMiddleware = this.middleware;
44+
while (currentMiddleware) {
45+
middlewareArray.push(currentMiddleware);
46+
if (typeof currentMiddleware.getNext !== "undefined") {
47+
currentMiddleware = currentMiddleware.getNext();
48+
} else {
49+
break;
50+
}
51+
}
52+
return middlewareArray;
53+
}
54+
55+
/**
56+
* @public
57+
* To set the middleware chain
58+
* @param {Middleware[]} middlewareArray - The array containing the middlewares
59+
*/
60+
public setMiddlewareArray(middlewareArray: Middleware[]) {
61+
for (let num = 0; num < middlewareArray.length - 1; num += 1) {
62+
middlewareArray[num].setNext(middlewareArray[num + 1]);
63+
}
64+
this.middleware = middlewareArray[0];
65+
}
66+
3667
/**
3768
* @public
3869
* @async

src/middleware/AuthenticationHandler.ts

+9
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,13 @@ export class AuthenticationHandler implements Middleware {
9494
public setNext(next: Middleware): void {
9595
this.nextMiddleware = next;
9696
}
97+
98+
/**
99+
* @public
100+
* To get the next middleware in the chain
101+
* @returns next Middleware instance
102+
*/
103+
public getNext(): Middleware {
104+
return this.nextMiddleware;
105+
}
97106
}

src/middleware/IMiddleware.ts

+1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ import { Context } from "../IContext";
1515
export interface Middleware {
1616
execute: (context: Context) => Promise<void>;
1717
setNext?: (middleware: Middleware) => void;
18+
getNext?: () => Middleware;
1819
}

src/middleware/RedirectHandler.ts

+9
Original file line numberDiff line numberDiff line change
@@ -243,4 +243,13 @@ export class RedirectHandler implements Middleware {
243243
public setNext(next: Middleware): void {
244244
this.nextMiddleware = next;
245245
}
246+
247+
/**
248+
* @public
249+
* To get the next middleware in the chain
250+
* @returns next Middleware instance
251+
*/
252+
public getNext(): Middleware {
253+
return this.nextMiddleware;
254+
}
246255
}

src/middleware/RetryHandler.ts

+9
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,13 @@ export class RetryHandler implements Middleware {
216216
public setNext(next: Middleware): void {
217217
this.nextMiddleware = next;
218218
}
219+
220+
/**
221+
* @public
222+
* To get the next middleware in the chain
223+
* @returns next Middleware instance
224+
*/
225+
public getNext(): Middleware {
226+
return this.nextMiddleware;
227+
}
219228
}

src/middleware/TelemetryHandler.ts

+9
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,13 @@ export class TelemetryHandler implements Middleware {
9696
public setNext(next: Middleware): void {
9797
this.nextMiddleware = next;
9898
}
99+
100+
/**
101+
* @public
102+
* To get the next middleware in the chain
103+
* @returns next Middleware instance
104+
*/
105+
public getNext(): Middleware {
106+
return this.nextMiddleware;
107+
}
99108
}

0 commit comments

Comments
 (0)