Skip to content
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

feat(middleware-user-agent): cache user agent string #3970

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,22 @@ describe("userAgentMiddleware", () => {
describe(runtime, () => {
for (const { ua, expected } of cases) {
it(`should sanitize user agent ${ua} to ${expected}`, async () => {
const defaultUserAgentProvider = jest.fn().mockReturnValue([ua]);
const middleware = userAgentMiddleware({
defaultUserAgentProvider: async () => [ua],
defaultUserAgentProvider,
runtime,
});
const handler = middleware(mockNextHandler, {});
await handler({ input: {}, request: new HttpRequest({ headers: {} }) });
expect(mockNextHandler.mock.calls[0][0].request.headers[sdkUserAgentKey]).toEqual(
expect.stringContaining(expected)
);
// should work when middleware is reused
await handler({ input: {}, request: new HttpRequest({ headers: {} }) });
expect(mockNextHandler.mock.calls[1][0].request.headers[sdkUserAgentKey]).toEqual(
mockNextHandler.mock.calls[0][0].request.headers[sdkUserAgentKey]
);
expect(defaultUserAgentProvider.mock.calls.length).toEqual(1);
});

it(`should include internal metadata, user agent ${ua} customization: ${expected}`, async () => {
Expand Down
46 changes: 26 additions & 20 deletions packages/middleware-user-agent/src/user-agent-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,31 +35,36 @@ import {
* config or middleware setting the `userAgent` context to generate desired user
* agent.
*/
export const userAgentMiddleware =
(options: UserAgentResolvedConfig) =>
<Output extends MetadataBearer>(
next: BuildHandler<any, any>,
context: HandlerExecutionContext
): BuildHandler<any, any> =>
async (args: BuildHandlerArguments<any>): Promise<BuildHandlerOutput<Output>> => {
export const userAgentMiddleware = (options: UserAgentResolvedConfig) => <Output extends MetadataBearer>(
next: BuildHandler<any, any>,
context: HandlerExecutionContext
): BuildHandler<any, any> => {
let sdkUserAgentValue = "";
let normalUAValue = "";
let initialized = false;
return async (args: BuildHandlerArguments<any>): Promise<BuildHandlerOutput<Output>> => {
const { request } = args;
if (!HttpRequest.isInstance(request)) return next(args);
const { headers } = request;
const userAgent = context?.userAgent?.map(escapeUserAgent) || [];
const defaultUserAgent = (await options.defaultUserAgentProvider()).map(escapeUserAgent);
const customUserAgent = options?.customUserAgent?.map(escapeUserAgent) || [];
const prefix = getUserAgentPrefix();

// Set value to AWS-specific user agent header
const sdkUserAgentValue = (prefix ? [prefix] : [])
.concat([...defaultUserAgent, ...userAgent, ...customUserAgent])
.join(SPACE);
if (!initialized) {
const userAgent = context?.userAgent?.map(escapeUserAgent) || [];
const defaultUserAgent = (await options.defaultUserAgentProvider()).map(escapeUserAgent);
const customUserAgent = options?.customUserAgent?.map(escapeUserAgent) || [];
const prefix = getUserAgentPrefix();

// Get value to be sent with non-AWS-specific user agent header.
const normalUAValue = [
...defaultUserAgent.filter((section) => section.startsWith("aws-sdk-")),
...customUserAgent,
].join(SPACE);
// Set value to AWS-specific user agent header
sdkUserAgentValue = (prefix ? [prefix] : [])
.concat([...defaultUserAgent, ...userAgent, ...customUserAgent])
.join(SPACE);

// Get value to be sent with non-AWS-specific user agent header.
normalUAValue = [
...defaultUserAgent.filter((section) => section.startsWith("aws-sdk-")),
...customUserAgent,
].join(SPACE);
initialized = true;
}

if (options.runtime !== "browser") {
if (normalUAValue) {
Expand All @@ -77,6 +82,7 @@ export const userAgentMiddleware =
request,
});
};
};

/**
* Escape the each pair according to https://tools.ietf.org/html/rfc5234 and join the pair with pattern `name/version`.
Expand Down