-
Notifications
You must be signed in to change notification settings - Fork 132
feat(node-http-handler): pass client logger to request handlers #2170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
kuhe
merged 18 commits into
smithy-lang:main
from
aBurmeseDev:feat/pass-client-logger-to-request-handler
Aug 13, 2026
Merged
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
bd1691b
feat(node-http-handler): pass client logger to request handlers
aBurmeseDev 65f4a95
Merge branch 'main' into feat/pass-client-logger-to-request-handler
aBurmeseDev 6671898
fix: cast logger value type in updateHttpClientConfig
aBurmeseDev 418fa74
simplify logger injection per team decision
aBurmeseDev 687f8e3
Merge branch 'main' into feat/pass-client-logger-to-request-handler
aBurmeseDev a43865a
remove nullish assignments and add truthy check
aBurmeseDev 8833c39
Merge branch 'main' into feat/pass-client-logger-to-request-handler
aBurmeseDev 6f96ae3
feat(core): offer client logger to request handlers as a fallback
aBurmeseDev 203c84e
test: cover fallback logger in handler specs
aBurmeseDev 25212ad
chore: record fallbackLogger in API snapshot
aBurmeseDev 0609b70
Merge branch 'main' into feat/pass-client-logger-to-request-handler
aBurmeseDev ada1408
Merge branch 'main' into feat/pass-client-logger-to-request-handler
aBurmeseDev d84a219
fix: read requestHandler in http handler extension config
aBurmeseDev 6c73415
fix: drop stale api snapshot entries from bad merge
aBurmeseDev 4f81d14
Merge branch 'main' into feat/pass-client-logger-to-request-handler
aBurmeseDev 9f3f1ee
refactor: inline the fallback logger key in handlers
aBurmeseDev fc65973
refactor(core): inline the fallback logger key and drop fallbackLogge…
aBurmeseDev 0fe930f
Merge branch 'main' into feat/pass-client-logger-to-request-handler
aBurmeseDev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| --- | ||
| "@smithy/core": minor | ||
| "@smithy/node-http-handler": minor | ||
| "@smithy/undici-http-handler": minor | ||
| --- | ||
|
|
||
| feat: offer the client logger to request handlers as a fallback, without overwriting a handler's own logger. A NoOpLogger is not offered, so handlers keep their own console-based defaults. | ||
|
|
||
| fix: `getHttpHandlerExtensionConfiguration` and `resolveHttpHandlerRuntimeConfig` now read and write `requestHandler` instead of `httpHandler`, which is the field clients actually populate. This changes the shape of the internal `HttpHandlerExtensionConfigType` and of the object returned by `resolveHttpHandlerRuntimeConfig`. |
130 changes: 130 additions & 0 deletions
130
...core/src/submodules/protocols/protocol-http/extensions/httpExtensionConfiguration.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| import { describe, expect, it, vi } from "vitest"; | ||
|
|
||
| import { FALLBACK_LOGGER } from "../fallbackLogger"; | ||
| import { getHttpHandlerExtensionConfiguration, resolveHttpHandlerRuntimeConfig } from "./httpExtensionConfiguration"; | ||
|
|
||
| describe("getHttpHandlerExtensionConfiguration", () => { | ||
| const createMockHandler = () => ({ | ||
| metadata: { handlerProtocol: "http/1.1" }, | ||
| handle: vi.fn(), | ||
| updateHttpClientConfig: vi.fn(), | ||
| httpHandlerConfigs: vi.fn().mockReturnValue({}), | ||
| }); | ||
|
|
||
| const createMockLogger = () => ({ | ||
| trace: vi.fn(), | ||
| debug: vi.fn(), | ||
| info: vi.fn(), | ||
| warn: vi.fn(), | ||
| error: vi.fn(), | ||
| }); | ||
|
|
||
| /** | ||
| * Stands in for the client's NoOpLogger, which is detected by constructor | ||
| * name to avoid a cross-submodule import. | ||
| */ | ||
| class NoOpLogger { | ||
| public trace = vi.fn(); | ||
| public debug = vi.fn(); | ||
| public info = vi.fn(); | ||
| public warn = vi.fn(); | ||
| public error = vi.fn(); | ||
| } | ||
|
|
||
| describe("client logger injection", () => { | ||
| it("offers the client logger to the handler under the fallback key", () => { | ||
| const handler = createMockHandler(); | ||
| const logger = createMockLogger(); | ||
|
|
||
| getHttpHandlerExtensionConfiguration({ requestHandler: handler, logger } as any); | ||
|
|
||
| expect(handler.updateHttpClientConfig).toHaveBeenCalledWith(FALLBACK_LOGGER, logger); | ||
| }); | ||
|
|
||
| it("does not assign the public logger key, so an explicit handler logger is never overwritten", () => { | ||
| const handler = createMockHandler(); | ||
| const logger = createMockLogger(); | ||
|
|
||
| getHttpHandlerExtensionConfiguration({ requestHandler: handler, logger } as any); | ||
|
|
||
| expect(handler.updateHttpClientConfig).not.toHaveBeenCalledWith("logger", expect.anything()); | ||
| expect(handler.updateHttpClientConfig).toHaveBeenCalledTimes(1); | ||
| }); | ||
|
|
||
| it("does not call updateHttpClientConfig when logger is not set", () => { | ||
| const handler = createMockHandler(); | ||
|
|
||
| getHttpHandlerExtensionConfiguration({ requestHandler: handler } as any); | ||
|
|
||
| expect(handler.updateHttpClientConfig).not.toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it("does not offer a NoOpLogger, so handlers keep their console defaults", () => { | ||
| const handler = createMockHandler(); | ||
|
|
||
| getHttpHandlerExtensionConfiguration({ requestHandler: handler, logger: new NoOpLogger() } as any); | ||
|
|
||
| expect(handler.updateHttpClientConfig).not.toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it("does not throw when no handler is present", () => { | ||
| const logger = createMockLogger(); | ||
|
|
||
| // should not throw | ||
| getHttpHandlerExtensionConfiguration({ logger } as any); | ||
| }); | ||
|
|
||
| it("does not throw for a handler that predates updateHttpClientConfig", () => { | ||
| const logger = createMockLogger(); | ||
| const legacyHandler = { metadata: {}, handle: vi.fn() }; | ||
|
|
||
| // should not throw | ||
| getHttpHandlerExtensionConfiguration({ requestHandler: legacyHandler, logger } as any); | ||
| }); | ||
| }); | ||
|
|
||
| describe("handler accessors read and write requestHandler", () => { | ||
| it("returns the handler that clients populate as requestHandler", () => { | ||
| const handler = createMockHandler(); | ||
|
|
||
| const extension = getHttpHandlerExtensionConfiguration({ requestHandler: handler } as any); | ||
|
|
||
| expect(extension.httpHandler()).toBe(handler); | ||
| }); | ||
|
|
||
| it("setHttpHandler replaces the handler seen by the runtime config", () => { | ||
| const handler = createMockHandler(); | ||
| const replacement = createMockHandler(); | ||
| const runtimeConfig = { requestHandler: handler } as any; | ||
|
|
||
| const extension = getHttpHandlerExtensionConfiguration(runtimeConfig); | ||
| extension.setHttpHandler(replacement as any); | ||
|
|
||
| expect(runtimeConfig.requestHandler).toBe(replacement); | ||
| expect(extension.httpHandler()).toBe(replacement); | ||
| }); | ||
|
|
||
| it("forwards updateHttpClientConfig and httpHandlerConfigs to the handler", () => { | ||
| const handler = createMockHandler(); | ||
|
|
||
| const extension = getHttpHandlerExtensionConfiguration({ requestHandler: handler } as any); | ||
| extension.updateHttpClientConfig("requestTimeout" as any, 1000 as any); | ||
| extension.httpHandlerConfigs(); | ||
|
|
||
| expect(handler.updateHttpClientConfig).toHaveBeenCalledWith("requestTimeout", 1000); | ||
| expect(handler.httpHandlerConfigs).toHaveBeenCalled(); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe("resolveHttpHandlerRuntimeConfig", () => { | ||
| it("emits the handler under requestHandler, matching what clients read", () => { | ||
| const handler = { metadata: {}, handle: vi.fn() } as any; | ||
|
|
||
| const runtimeConfig = resolveHttpHandlerRuntimeConfig({ | ||
| httpHandler: () => handler, | ||
| } as any); | ||
|
|
||
| expect(runtimeConfig).toEqual({ requestHandler: handler }); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
packages/core/src/submodules/protocols/protocol-http/fallbackLogger.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| /** | ||
| * Key with which a client offers its logger to an HttpHandler via | ||
| * `updateHttpClientConfig`, to be used only if the handler has no logger | ||
| * of its own. | ||
| * | ||
| * A symbol keeps this off the handlers' public options types, and being a | ||
| * symbol already distinguishes it from the `"logger"` string key. | ||
| * `Symbol.for` means handlers can declare their own copy of this key and | ||
| * still compare equal to it. | ||
| * | ||
| * @internal | ||
| */ | ||
| export const FALLBACK_LOGGER = Symbol.for("logger"); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inlined in both handlers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also inlined it at the offer site in
httpExtensionConfig.tswhich let me dropfallbackLogger.tsentirely since it only existed to export that one.