Skip to content

Commit 8ad0ded

Browse files
jeskewsrchase
authored andcommitted
Add a serialize middleware step to keep from having to check if the request exists in all build middleware
1 parent e97e111 commit 8ad0ded

File tree

3 files changed

+64
-29
lines changed

3 files changed

+64
-29
lines changed

packages/middleware-content-length/src/index.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@ export function contentLengthMiddleware(
1414
): BuildHandler<any, Output, any> => async (
1515
args: BuildHandlerArguments<any, any>
1616
): Promise<Output> => {
17-
const {request} = args;
18-
if (!request) {
19-
throw new Error('Unable to determine request content-length due to missing request.');
20-
}
21-
17+
let request = {...args.request};
2218
const {body, headers} = request;
2319
if (
2420
body &&
@@ -28,7 +24,10 @@ export function contentLengthMiddleware(
2824
) {
2925
const length = bodyLengthCalculator(body);
3026
if (length !== undefined) {
31-
headers['Content-Length'] = String(length);
27+
request.headers = {
28+
...request.headers,
29+
'Content-Length': String(length),
30+
}
3231
}
3332
}
3433

packages/middleware-stack/src/index.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import {
55
Middleware,
66
MiddlewareStack as IMiddlewareStack,
77
HandlerExecutionContext,
8+
Step,
89
} from '@aws/types';
910

10-
export type Step = 'initialize'|'build'|'finalize';
11-
1211
interface HandlerListEntry<
1312
Input extends object,
1413
Output extends object,
@@ -20,11 +19,17 @@ interface HandlerListEntry<
2019
tags?: {[tag: string]: any};
2120
}
2221

22+
export interface MiddlewareStack<
23+
Input extends object,
24+
Output extends object,
25+
Stream = Uint8Array
26+
> extends IMiddlewareStack<Input, Output, Stream> {}
27+
2328
export class MiddlewareStack<
2429
Input extends object,
2530
Output extends object,
2631
Stream = Uint8Array
27-
> implements IMiddlewareStack<Input, Output, Stream> {
32+
> {
2833
private readonly entries: Array<HandlerListEntry<Input, Output, Stream>> = [];
2934
private sorted: boolean = true;
3035

@@ -117,7 +122,8 @@ export class MiddlewareStack<
117122
}
118123

119124
const stepWeights = {
120-
initialize: 3,
125+
initialize: 4,
126+
serialize: 3,
121127
build: 2,
122128
finalize: 1,
123129
};

packages/types/src/middleware.ts

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export interface HandlerArguments<Input extends object> {
1010
input: Input;
1111
}
1212

13-
export interface BuildHandlerArguments<
13+
export interface SerializeHandlerArguments<
1414
Input extends object,
1515
Stream = Uint8Array
1616
> extends HandlerArguments<Input> {
@@ -29,13 +29,15 @@ export interface FinalizeHandlerArguments<
2929
> extends HandlerArguments<Input> {
3030
/**
3131
* The user input serialized as an HTTP request.
32-
*
33-
* During the finalize phase of the execution of a middleware stack, a built
34-
* HTTP request will always be available.
3532
*/
3633
request: HttpRequest<Stream>;
3734
}
3835

36+
export interface BuildHandlerArguments<
37+
Input extends object,
38+
Stream = Uint8Array
39+
> extends FinalizeHandlerArguments<Input, Stream> {}
40+
3941
export interface Handler<Input extends object, Output extends object> {
4042
/**
4143
* Asynchronously converts an input object into an output object.
@@ -46,7 +48,7 @@ export interface Handler<Input extends object, Output extends object> {
4648
(args: HandlerArguments<Input>): Promise<Output>;
4749
}
4850

49-
export interface BuildHandler<
51+
export interface SerializeHandler<
5052
Input extends object,
5153
Output extends object,
5254
Stream = Uint8Array
@@ -57,7 +59,7 @@ export interface BuildHandler<
5759
* @param args An object containing a input to the command as well as any
5860
* associated or previously generated execution artifacts.
5961
*/
60-
(args: BuildHandlerArguments<Input, Stream>): Promise<Output>;
62+
(args: SerializeHandlerArguments<Input, Stream>): Promise<Output>;
6163
}
6264

6365
export interface FinalizeHandler<
@@ -74,6 +76,12 @@ export interface FinalizeHandler<
7476
(args: FinalizeHandlerArguments<Input, Stream>): Promise<Output>;
7577
}
7678

79+
export interface BuildHandler<
80+
Input extends object,
81+
Output extends object,
82+
Stream = Uint8Array
83+
> extends FinalizeHandler<Input, Output, Stream> {}
84+
7785
/**
7886
* A factory function that creates functions implementing the {Handler}
7987
* interface.
@@ -95,7 +103,7 @@ export interface Middleware<Input extends object, Output extends object> {
95103
* A factory function that creates functions implementing the {BuildHandler}
96104
* interface.
97105
*/
98-
export interface BuildMiddleware<
106+
export interface SerializeMiddleware<
99107
Input extends object,
100108
Output extends object,
101109
Stream = Uint8Array
@@ -107,12 +115,11 @@ export interface BuildMiddleware<
107115
* @param context Invariant data and functions for use by the handler.
108116
*/
109117
(
110-
next: BuildHandler<Input, Output, Stream>,
118+
next: SerializeHandler<Input, Output, Stream>,
111119
context: HandlerExecutionContext
112-
): BuildHandler<Input, Output, Stream>;
120+
): SerializeHandler<Input, Output, Stream>;
113121
}
114122

115-
116123
/**
117124
* A factory function that creates functions implementing the {FinalizeHandler}
118125
* interface.
@@ -134,6 +141,12 @@ export interface FinalizeMiddleware<
134141
): FinalizeHandler<Input, Output, Stream>;
135142
}
136143

144+
export interface BuildMiddleware<
145+
Input extends object,
146+
Output extends object,
147+
Stream = Uint8Array
148+
> extends FinalizeMiddleware<Input, Output, Stream> {}
149+
137150
/**
138151
* A factory function that creates the terminal handler atop which a middleware
139152
* stack sits.
@@ -147,20 +160,24 @@ export interface Terminalware<
147160
): FinalizeHandler<Input, Output, Stream>;
148161
}
149162

150-
export type Step = 'initialize'|'build'|'finalize';
163+
export type Step = 'initialize'|'serialize'|'build'|'finalize';
151164

152165
export interface HandlerOptions {
153166
/**
154167
* Handlers are ordered using a "step" that describes the stage of command
155168
* execution at which the handler will be executed. The available steps are:
156169
*
157-
* - initialize: The input is being prepared and validated. Examples of
158-
* typical initialization tasks include injecting default options and
159-
* parameter validation.
160-
* - build: The input is being serialized into an HTTP request. The input
161-
* should not be altered in middleware occupying this step, as it may
162-
* have already been serialized into a request. Examples of typical
163-
* build tasks include request construction and injecting HTTP headers.
170+
* - initialize: The input is being prepared. Examples of typical
171+
* initialization tasks include injecting default options computing
172+
* derived parameters.
173+
* - serialize: The input is complete and ready to be serialized. Examples
174+
* of typical serialization tasks include input validation and building
175+
* an HTTP request from user input.
176+
* - build: The input has been serialized into an HTTP request, but that
177+
* request may require further modification. Any request alterations
178+
* will be applied to all retries. Examples of typical build tasks
179+
* include injecting HTTP headers that describe a stable aspect of the
180+
* request, such as `Content-Length` or a body checksum.
164181
* - finalize: The request is being prepared to be sent over the wire. The
165182
* request in this stage should already be semantically complete and
166183
* should therefore only be altered as match the recipient's
@@ -194,6 +211,10 @@ export interface HandlerOptions {
194211
tags?: {[tag: string]: any};
195212
}
196213

214+
export interface SerializeHandlerOptions extends HandlerOptions {
215+
step: 'serialize';
216+
}
217+
197218
export interface BuildHandlerOptions extends HandlerOptions {
198219
step: 'build';
199220
}
@@ -215,12 +236,21 @@ export interface MiddlewareStack<
215236
options?: HandlerOptions & {step?: 'initialize'}
216237
): void;
217238

239+
/**
240+
* Add middleware to the list to be executed during the "serialize" phase,
241+
* optionally specifying a priority and tags.
242+
*/
243+
add(
244+
middleware: Middleware<Input, Output>,
245+
options: SerializeHandlerOptions
246+
): void;
247+
218248
/**
219249
* Add middleware to the list to be executed during the "build" phase,
220250
* optionally specifying a priority and tags.
221251
*/
222252
add(
223-
middleware: BuildMiddleware<Input, Output, Stream>,
253+
middleware: FinalizeMiddleware<Input, Output, Stream>,
224254
options: BuildHandlerOptions
225255
): void;
226256

0 commit comments

Comments
 (0)