Skip to content

Commit fc98d2d

Browse files
authored
fix(clients): remove retry headers for several services (#1789)
* fix(clients-*): remove retry headers for serveral services ConnectParticipant, IoT Data Plane, IoT, Pinpoint SMS Voice, QLDB doesn't support retry headers per their CORS config. So remove the support for these service to unblock the browser usage * feat(middleware-retry): move omitRetryHeadersMiddleware before signing
1 parent d4cb977 commit fc98d2d

File tree

12 files changed

+200
-8
lines changed

12 files changed

+200
-8
lines changed

clients/client-connectparticipant/ConnectParticipantClient.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,13 @@ import {
2626
resolveHostHeaderConfig,
2727
} from "@aws-sdk/middleware-host-header";
2828
import { getLoggerPlugin } from "@aws-sdk/middleware-logger";
29-
import { RetryInputConfig, RetryResolvedConfig, getRetryPlugin, resolveRetryConfig } from "@aws-sdk/middleware-retry";
29+
import {
30+
RetryInputConfig,
31+
RetryResolvedConfig,
32+
getOmitRetryHeadersPlugin,
33+
getRetryPlugin,
34+
resolveRetryConfig,
35+
} from "@aws-sdk/middleware-retry";
3036
import {
3137
AwsAuthInputConfig,
3238
AwsAuthResolvedConfig,
@@ -223,6 +229,7 @@ export class ConnectParticipantClient extends __Client<
223229
this.middlewareStack.use(getHostHeaderPlugin(this.config));
224230
this.middlewareStack.use(getLoggerPlugin(this.config));
225231
this.middlewareStack.use(getUserAgentPlugin(this.config));
232+
this.middlewareStack.use(getOmitRetryHeadersPlugin(this.config));
226233
}
227234

228235
destroy(): void {

clients/client-iot-data-plane/IoTDataPlaneClient.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ import {
2323
resolveHostHeaderConfig,
2424
} from "@aws-sdk/middleware-host-header";
2525
import { getLoggerPlugin } from "@aws-sdk/middleware-logger";
26-
import { RetryInputConfig, RetryResolvedConfig, getRetryPlugin, resolveRetryConfig } from "@aws-sdk/middleware-retry";
26+
import {
27+
RetryInputConfig,
28+
RetryResolvedConfig,
29+
getOmitRetryHeadersPlugin,
30+
getRetryPlugin,
31+
resolveRetryConfig,
32+
} from "@aws-sdk/middleware-retry";
2733
import {
2834
AwsAuthInputConfig,
2935
AwsAuthResolvedConfig,
@@ -225,6 +231,7 @@ export class IoTDataPlaneClient extends __Client<
225231
this.middlewareStack.use(getHostHeaderPlugin(this.config));
226232
this.middlewareStack.use(getLoggerPlugin(this.config));
227233
this.middlewareStack.use(getUserAgentPlugin(this.config));
234+
this.middlewareStack.use(getOmitRetryHeadersPlugin(this.config));
228235
}
229236

230237
destroy(): void {

clients/client-iot/IoTClient.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,13 @@ import {
596596
resolveHostHeaderConfig,
597597
} from "@aws-sdk/middleware-host-header";
598598
import { getLoggerPlugin } from "@aws-sdk/middleware-logger";
599-
import { RetryInputConfig, RetryResolvedConfig, getRetryPlugin, resolveRetryConfig } from "@aws-sdk/middleware-retry";
599+
import {
600+
RetryInputConfig,
601+
RetryResolvedConfig,
602+
getOmitRetryHeadersPlugin,
603+
getRetryPlugin,
604+
resolveRetryConfig,
605+
} from "@aws-sdk/middleware-retry";
600606
import {
601607
AwsAuthInputConfig,
602608
AwsAuthResolvedConfig,
@@ -1217,6 +1223,7 @@ export class IoTClient extends __Client<
12171223
this.middlewareStack.use(getHostHeaderPlugin(this.config));
12181224
this.middlewareStack.use(getLoggerPlugin(this.config));
12191225
this.middlewareStack.use(getUserAgentPlugin(this.config));
1226+
this.middlewareStack.use(getOmitRetryHeadersPlugin(this.config));
12201227
}
12211228

12221229
destroy(): void {

clients/client-pinpoint-sms-voice/PinpointSMSVoiceClient.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ import {
4444
resolveHostHeaderConfig,
4545
} from "@aws-sdk/middleware-host-header";
4646
import { getLoggerPlugin } from "@aws-sdk/middleware-logger";
47-
import { RetryInputConfig, RetryResolvedConfig, getRetryPlugin, resolveRetryConfig } from "@aws-sdk/middleware-retry";
47+
import {
48+
RetryInputConfig,
49+
RetryResolvedConfig,
50+
getOmitRetryHeadersPlugin,
51+
getRetryPlugin,
52+
resolveRetryConfig,
53+
} from "@aws-sdk/middleware-retry";
4854
import {
4955
AwsAuthInputConfig,
5056
AwsAuthResolvedConfig,
@@ -242,6 +248,7 @@ export class PinpointSMSVoiceClient extends __Client<
242248
this.middlewareStack.use(getHostHeaderPlugin(this.config));
243249
this.middlewareStack.use(getLoggerPlugin(this.config));
244250
this.middlewareStack.use(getUserAgentPlugin(this.config));
251+
this.middlewareStack.use(getOmitRetryHeadersPlugin(this.config));
245252
}
246253

247254
destroy(): void {

clients/client-qldb/QLDBClient.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ import {
5858
resolveHostHeaderConfig,
5959
} from "@aws-sdk/middleware-host-header";
6060
import { getLoggerPlugin } from "@aws-sdk/middleware-logger";
61-
import { RetryInputConfig, RetryResolvedConfig, getRetryPlugin, resolveRetryConfig } from "@aws-sdk/middleware-retry";
61+
import {
62+
RetryInputConfig,
63+
RetryResolvedConfig,
64+
getOmitRetryHeadersPlugin,
65+
getRetryPlugin,
66+
resolveRetryConfig,
67+
} from "@aws-sdk/middleware-retry";
6268
import {
6369
AwsAuthInputConfig,
6470
AwsAuthResolvedConfig,
@@ -278,6 +284,7 @@ export class QLDBClient extends __Client<
278284
this.middlewareStack.use(getHostHeaderPlugin(this.config));
279285
this.middlewareStack.use(getLoggerPlugin(this.config));
280286
this.middlewareStack.use(getUserAgentPlugin(this.config));
287+
this.middlewareStack.use(getOmitRetryHeadersPlugin(this.config));
281288
}
282289

283290
destroy(): void {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.smithy.aws.typescript.codegen;
17+
18+
import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_MIDDLEWARE;
19+
20+
import java.util.List;
21+
import java.util.Set;
22+
23+
import software.amazon.smithy.aws.traits.ServiceTrait;
24+
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
25+
import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin;
26+
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
27+
import software.amazon.smithy.utils.ListUtils;
28+
import software.amazon.smithy.utils.SetUtils;
29+
30+
31+
public class AddOmitRetryHeadersDependency implements TypeScriptIntegration {
32+
private static final Set<String> SERVICE_IDS = SetUtils.of(
33+
"ConnectParticipant",
34+
"IoT Data Plane",
35+
"IoT",
36+
"Pinpoint SMS Voice",
37+
"QLDB"
38+
);
39+
40+
@Override
41+
public List<RuntimeClientPlugin> getClientPlugins() {
42+
return ListUtils.of(
43+
RuntimeClientPlugin.builder()
44+
.withConventions(TypeScriptDependency.MIDDLEWARE_RETRY.dependency, "OmitRetryHeaders",
45+
HAS_MIDDLEWARE)
46+
.servicePredicate((m, s) -> {
47+
String sdkId = s.getTrait(ServiceTrait.class).map(ServiceTrait::getSdkId).orElse("");
48+
return SERVICE_IDS.contains(sdkId);
49+
})
50+
.build()
51+
);
52+
}
53+
}

codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ software.amazon.smithy.aws.typescript.codegen.AddEventStreamHandlingDependency
1313
software.amazon.smithy.aws.typescript.codegen.AddHttp2Dependency
1414
software.amazon.smithy.aws.typescript.codegen.AddTranscribeStreamingDependency
1515
software.amazon.smithy.aws.typescript.codegen.AddUserAgentDependency
16+
software.amazon.smithy.aws.typescript.codegen.AddOmitRetryHeadersDependency

packages/middleware-retry/src/constants.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,13 @@ export const TIMEOUT_RETRY_COST = 10;
3737
* if an SDK operation invocation succeeds without requiring a retry request.
3838
*/
3939
export const NO_RETRY_INCREMENT = 1;
40+
41+
/**
42+
* Header name for SDK invocation ID
43+
*/
44+
export const INVOCATION_ID_HEADER = "amz-sdk-invocation-id";
45+
46+
/**
47+
* Header name for request retry information.
48+
*/
49+
export const REQUEST_HEADER = "amz-sdk-request";

packages/middleware-retry/src/defaultStrategy.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ import { SdkError } from "@aws-sdk/smithy-client";
44
import { FinalizeHandler, FinalizeHandlerArguments, MetadataBearer, Provider, RetryStrategy } from "@aws-sdk/types";
55
import { v4 } from "uuid";
66

7-
import { DEFAULT_RETRY_DELAY_BASE, INITIAL_RETRY_TOKENS, THROTTLING_RETRY_DELAY_BASE } from "./constants";
7+
import {
8+
DEFAULT_RETRY_DELAY_BASE,
9+
INITIAL_RETRY_TOKENS,
10+
INVOCATION_ID_HEADER,
11+
REQUEST_HEADER,
12+
THROTTLING_RETRY_DELAY_BASE,
13+
} from "./constants";
814
import { getDefaultRetryQuota } from "./defaultRetryQuota";
915
import { defaultDelayDecider } from "./delayDecider";
1016
import { defaultRetryDecider } from "./retryDecider";
@@ -108,13 +114,13 @@ export class StandardRetryStrategy implements RetryStrategy {
108114

109115
const { request } = args;
110116
if (HttpRequest.isInstance(request)) {
111-
request.headers["amz-sdk-invocation-id"] = v4();
117+
request.headers[INVOCATION_ID_HEADER] = v4();
112118
}
113119

114120
while (true) {
115121
try {
116122
if (HttpRequest.isInstance(request)) {
117-
request.headers["amz-sdk-request"] = `attempt=${attempts + 1}; max=${maxAttempts}`;
123+
request.headers[REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`;
118124
}
119125
const { response, output } = await next(args);
120126

packages/middleware-retry/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from "./retryMiddleware";
2+
export * from "./omitRetryHeadersMiddleware";
23
export * from "./defaultStrategy";
34
export * from "./configurations";
45
export * from "./delayDecider";
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { HttpRequest } from "@aws-sdk/protocol-http";
2+
import { FinalizeHandlerArguments, MiddlewareStack } from "@aws-sdk/types";
3+
4+
import { INVOCATION_ID_HEADER, REQUEST_HEADER } from "./constants";
5+
import {
6+
getOmitRetryHeadersPlugin,
7+
omitRetryHeadersMiddleware,
8+
omitRetryHeadersMiddlewareOptions,
9+
} from "./omitRetryHeadersMiddleware";
10+
11+
describe("getOmitRetryHeadersPlugin", () => {
12+
const mockClientStack = {
13+
add: jest.fn(),
14+
addRelativeTo: jest.fn(),
15+
};
16+
17+
afterEach(() => {
18+
jest.clearAllMocks();
19+
});
20+
21+
it(`adds omitRetryHeadersMiddleware`, () => {
22+
getOmitRetryHeadersPlugin({}).applyToStack((mockClientStack as unknown) as MiddlewareStack<any, any>);
23+
expect(mockClientStack.addRelativeTo).toHaveBeenCalledTimes(1);
24+
expect(mockClientStack.addRelativeTo.mock.calls[0][1]).toEqual(omitRetryHeadersMiddlewareOptions);
25+
});
26+
});
27+
28+
describe("omitRetryHeadersMiddleware", () => {
29+
afterEach(() => {
30+
jest.clearAllMocks();
31+
});
32+
33+
it("remove retry headers", async () => {
34+
const next = jest.fn();
35+
const args = {
36+
request: new HttpRequest({
37+
headers: {
38+
[INVOCATION_ID_HEADER]: "12345",
39+
[REQUEST_HEADER]: "maxAttempts=30",
40+
},
41+
}),
42+
};
43+
44+
await omitRetryHeadersMiddleware()(next)(args as FinalizeHandlerArguments<any>);
45+
expect(next).toHaveBeenCalledTimes(1);
46+
expect(next.mock.calls[0][0].request.headers[INVOCATION_ID_HEADER]).toBeUndefined();
47+
expect(next.mock.calls[0][0].request.headers[REQUEST_HEADER]).toBeUndefined();
48+
});
49+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { HttpRequest } from "@aws-sdk/protocol-http";
2+
import {
3+
FinalizeHandler,
4+
FinalizeHandlerArguments,
5+
FinalizeHandlerOutput,
6+
MetadataBearer,
7+
Pluggable,
8+
RelativeMiddlewareOptions,
9+
} from "@aws-sdk/types";
10+
11+
import { INVOCATION_ID_HEADER, REQUEST_HEADER } from "./constants";
12+
13+
export const omitRetryHeadersMiddleware = () => <Output extends MetadataBearer = MetadataBearer>(
14+
next: FinalizeHandler<any, Output>
15+
): FinalizeHandler<any, Output> => async (
16+
args: FinalizeHandlerArguments<any>
17+
): Promise<FinalizeHandlerOutput<Output>> => {
18+
const { request } = args;
19+
if (HttpRequest.isInstance(request)) {
20+
delete request.headers[INVOCATION_ID_HEADER];
21+
delete request.headers[REQUEST_HEADER];
22+
}
23+
return next(args);
24+
};
25+
26+
export const omitRetryHeadersMiddlewareOptions: RelativeMiddlewareOptions = {
27+
name: "omitRetryHeadersMiddleware",
28+
tags: ["RETRY", "HEADERS", "OMIT_RETRY_HEADERS"],
29+
relation: "before",
30+
toMiddleware: "awsAuthMiddleware",
31+
};
32+
33+
export const getOmitRetryHeadersPlugin = (options: unknown): Pluggable<any, any> => ({
34+
applyToStack: (clientStack) => {
35+
clientStack.addRelativeTo(omitRetryHeadersMiddleware(), omitRetryHeadersMiddlewareOptions);
36+
},
37+
});

0 commit comments

Comments
 (0)