Skip to content

Commit a27fa86

Browse files
authored
feat(middleware-stack): add filter() function to middleware stack (#241)
1 parent 8bf91e2 commit a27fa86

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

packages/middleware-stack/src/index.spec.ts

+67-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import {
66
Middleware,
77
HandlerExecutionContext,
88
FinalizeMiddleware,
9-
FinalizeHandler
9+
FinalizeHandler,
10+
BuildMiddleware
1011
} from "@aws-sdk/types";
1112

1213
type input = Array<string>;
@@ -170,4 +171,69 @@ describe("MiddlewareStack", () => {
170171
{} as any
171172
)({ input: [] });
172173
});
174+
175+
it("should allow filtering of middlewares by middleware options", async () => {
176+
const stack = new MiddlewareStack<input, output>();
177+
stack.add(getConcatMiddleware("first") as Middleware<input, output>, {
178+
priority: 1
179+
});
180+
stack.add(getConcatMiddleware("second") as Middleware<input, output>, {
181+
tags: { foo: true, bar: true }
182+
});
183+
stack.add(getConcatMiddleware("third") as Middleware<input, output>, {
184+
step: "initialize"
185+
});
186+
stack.add(getConcatMiddleware("fourth") as Middleware<input, output>, {
187+
step: "serialize"
188+
});
189+
stack.add(getConcatMiddleware("fifth") as BuildMiddleware<input, output>, {
190+
step: "build"
191+
});
192+
stack.add(
193+
getConcatMiddleware("sixth") as FinalizeMiddleware<input, output>,
194+
{
195+
step: "finalize"
196+
}
197+
);
198+
const filteredStack = stack.filter(middlewareStats => {
199+
return (
200+
middlewareStats.priority === 1 ||
201+
(middlewareStats.tags && middlewareStats.tags.foo === true) ||
202+
middlewareStats.step === "initialize"
203+
);
204+
});
205+
const handler = jest.fn(({ input }: FinalizeHandlerArguments<input>) => {
206+
expect(input).toEqual(["first", "third", "second"]);
207+
return {};
208+
});
209+
210+
const composed = filteredStack.resolve(handler, {} as any);
211+
await composed({ input: [] });
212+
213+
expect(handler.mock.calls.length).toBe(1);
214+
});
215+
216+
it("should not allow altering stack that to be filtered", async () => {
217+
const stack = new MiddlewareStack<input, output>();
218+
stack.add(getConcatMiddleware("first") as Middleware<input, output>, {
219+
priority: 1
220+
});
221+
stack.add(getConcatMiddleware("second") as Middleware<input, output>, {
222+
tags: { foo: true, bar: true, baz: true }
223+
});
224+
const filteredStack = stack.filter(middlewareStats => {
225+
if (middlewareStats.tags!.baz) {
226+
//try make "second" middleware prior to "first" middleware
227+
middlewareStats.priority = 100;
228+
}
229+
return true;
230+
});
231+
let inner = jest.fn(({ input }: FinalizeHandlerArguments<input>) => {
232+
expect(input).toEqual(["first", "second"]);
233+
return Promise.resolve({});
234+
});
235+
await filteredStack.resolve(inner, {} as any)({ input: [] });
236+
237+
expect(inner.mock.calls.length).toBe(1);
238+
});
173239
});

packages/middleware-stack/src/index.ts

+20
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,26 @@ export class MiddlewareStack<
9898
return this.entries.length < length;
9999
}
100100

101+
filter(
102+
callbackfn: (handlerOptions: HandlerOptions) => boolean
103+
): MiddlewareStack<Input, Output, Stream> {
104+
const filtered = new MiddlewareStack<Input, Output, Stream>();
105+
for (const entry of this.entries) {
106+
const options: HandlerOptions = {
107+
step: entry.step,
108+
priority: entry.priority,
109+
tags: {
110+
...entry.tags
111+
}
112+
};
113+
if (callbackfn(options)) {
114+
filtered.entries.push(entry);
115+
}
116+
}
117+
filtered.sorted = this.sorted;
118+
return filtered;
119+
}
120+
101121
resolve<InputType extends Input, OutputType extends Output>(
102122
handler: FinalizeHandler<InputType, OutputType, Stream>,
103123
context: HandlerExecutionContext

0 commit comments

Comments
 (0)