Skip to content

Commit 16bdb05

Browse files
committed
feat: implement shared http client
1 parent 6b853ff commit 16bdb05

File tree

4 files changed

+51
-0
lines changed

4 files changed

+51
-0
lines changed

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@
521521
"@smithy/service-error-classification": "^3.0.0",
522522
"@smithy/shared-ini-file-loader": "^3.0.0",
523523
"@smithy/util-retry": "^3.0.0",
524+
"@smithy/node-http-handler": "^3.0.0",
524525
"@vscode/debugprotocol": "^1.57.0",
525526
"@zip.js/zip.js": "^2.7.41",
526527
"adm-zip": "^0.5.10",

packages/core/src/shared/awsClientBuilderV3.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
RetryStrategy,
2626
UserAgent,
2727
} from '@aws-sdk/types'
28+
import { NodeHttpHandler } from '@smithy/node-http-handler'
2829
import { HttpResponse, HttpRequest } from '@aws-sdk/protocol-http'
2930
import { ConfiguredRetryStrategy } from '@smithy/util-retry'
3031
import { telemetry } from './telemetry/telemetry'
@@ -33,6 +34,8 @@ import { extensionVersion } from './vscode/env'
3334
import { getLogger } from './logger/logger'
3435
import { partialClone } from './utilities/collectionUtils'
3536
import { selectFrom } from './utilities/tsUtils'
37+
import { Agent } from 'http'
38+
import { once } from './utilities/functionUtils'
3639

3740
export type AwsClientConstructor<C> = new (o: AwsClientOptions) => C
3841

@@ -88,6 +91,16 @@ export class AWSClientBuilderV3 {
8891
return shim
8992
}
9093

94+
private buildHttpClient() {
95+
return new NodeHttpHandler({
96+
httpAgent: new Agent({ keepAlive: true, timeout: 30000 }),
97+
httpsAgent: new Agent({ keepAlive: true, timeout: 30000 }),
98+
logger: getLogger(),
99+
})
100+
}
101+
102+
private getHttpClient = once(this.buildHttpClient.bind(this))
103+
91104
private keyAwsService<C extends AwsClient>(serviceOptions: AwsServiceOptions<C>): string {
92105
// Serializing certain objects in the args allows us to detect when nested objects change (ex. new retry strategy, endpoints)
93106
return [
@@ -129,6 +142,10 @@ export class AWSClientBuilderV3 {
129142
// Simple exponential backoff strategy as default.
130143
opt.retryStrategy = new ConfiguredRetryStrategy(5, (attempt: number) => 1000 * 2 ** attempt)
131144
}
145+
146+
if (!opt.requestHandler) {
147+
opt.requestHandler = this.getHttpClient()
148+
}
132149
// TODO: add tests for refresh logic.
133150
opt.credentials = async () => {
134151
const creds = await shim.get()

packages/core/src/test/shared/awsClientBuilderV3.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { Credentials, MetadataBearer, MiddlewareStack } from '@aws-sdk/types'
3232
import { oneDay } from '../../shared/datetime'
3333
import { ConfiguredRetryStrategy } from '@smithy/util-retry'
3434
import { StandardRetryStrategy } from '@smithy/util-retry'
35+
import { NodeHttpHandler } from '@smithy/node-http-handler'
3536

3637
describe('AwsClientBuilderV3', function () {
3738
let builder: AWSClientBuilderV3
@@ -77,6 +78,37 @@ describe('AwsClientBuilderV3', function () {
7778
assert.strictEqual(service.config.userAgent[0][0], 'CUSTOM USER AGENT')
7879
})
7980

81+
it('injects http client into client', async function () {
82+
const requestHandler = new NodeHttpHandler({
83+
requestTimeout: 1234,
84+
})
85+
const service = await builder.createAwsService({
86+
serviceClient: Client,
87+
clientOptions: {
88+
requestHandler: requestHandler,
89+
},
90+
})
91+
assert.strictEqual(service.config.requestHandler, requestHandler)
92+
})
93+
94+
it('defaults to same http client', async function () {
95+
const service = await builder.createAwsService({
96+
serviceClient: Client,
97+
})
98+
const service2 = await builder.createAwsService({
99+
serviceClient: Client,
100+
})
101+
// Check if request handlers are reference-equal.
102+
const firstHandler = service.config.requestHandler
103+
const secondHandler = service2.config.requestHandler
104+
105+
if (firstHandler instanceof NodeHttpHandler && secondHandler instanceof NodeHttpHandler) {
106+
assert.ok(firstHandler === secondHandler)
107+
} else {
108+
assert.fail('Expected both request handlers to be NodeHttpHandler instances')
109+
}
110+
})
111+
80112
describe('caching mechanism', function () {
81113
it('avoids recreating client on duplicate calls', async function () {
82114
const firstClient = await builder.getAwsService({ serviceClient: TestClient })

0 commit comments

Comments
 (0)