'use strict'; var core = require('@smithy/core'); var utilEndpoints = require('@aws-sdk/util-endpoints'); var protocolHttp = require('@smithy/protocol-http'); var core$1 = require('@aws-sdk/core'); const DEFAULT_UA_APP_ID = undefined; function isValidUserAgentAppId(appId) { if (appId === undefined) { return true; } return typeof appId === "string" && appId.length <= 50; } function resolveUserAgentConfig(input) { const normalizedAppIdProvider = core.normalizeProvider(input.userAgentAppId ?? DEFAULT_UA_APP_ID); const { customUserAgent } = input; return Object.assign(input, { customUserAgent: typeof customUserAgent === "string" ? [[customUserAgent]] : customUserAgent, userAgentAppId: async () => { const appId = await normalizedAppIdProvider(); if (!isValidUserAgentAppId(appId)) { const logger = input.logger?.constructor?.name === "NoOpLogger" || !input.logger ? console : input.logger; if (typeof appId !== "string") { logger?.warn("userAgentAppId must be a string or undefined."); } else if (appId.length > 50) { logger?.warn("The provided userAgentAppId exceeds the maximum length of 50 characters."); } } return appId; }, }); } const ACCOUNT_ID_ENDPOINT_REGEX = /\d{12}\.ddb/; async function checkFeatures(context, config, args) { const request = args.request; if (request?.headers?.["smithy-protocol"] === "rpc-v2-cbor") { core$1.setFeature(context, "PROTOCOL_RPC_V2_CBOR", "M"); } if (typeof config.retryStrategy === "function") { const retryStrategy = await config.retryStrategy(); if (typeof retryStrategy.acquireInitialRetryToken === "function") { if (retryStrategy.constructor?.name?.includes("Adaptive")) { core$1.setFeature(context, "RETRY_MODE_ADAPTIVE", "F"); } else { core$1.setFeature(context, "RETRY_MODE_STANDARD", "E"); } } else { core$1.setFeature(context, "RETRY_MODE_LEGACY", "D"); } } if (typeof config.accountIdEndpointMode === "function") { const endpointV2 = context.endpointV2; if (String(endpointV2?.url?.hostname).match(ACCOUNT_ID_ENDPOINT_REGEX)) { core$1.setFeature(context, "ACCOUNT_ID_ENDPOINT", "O"); } switch (await config.accountIdEndpointMode?.()) { case "disabled": core$1.setFeature(context, "ACCOUNT_ID_MODE_DISABLED", "Q"); break; case "preferred": core$1.setFeature(context, "ACCOUNT_ID_MODE_PREFERRED", "P"); break; case "required": core$1.setFeature(context, "ACCOUNT_ID_MODE_REQUIRED", "R"); break; } } const identity = context.__smithy_context?.selectedHttpAuthScheme?.identity; if (identity?.$source) { const credentials = identity; if (credentials.accountId) { core$1.setFeature(context, "RESOLVED_ACCOUNT_ID", "T"); } for (const [key, value] of Object.entries(credentials.$source ?? {})) { core$1.setFeature(context, key, value); } } } const USER_AGENT = "user-agent"; const X_AMZ_USER_AGENT = "x-amz-user-agent"; const SPACE = " "; const UA_NAME_SEPARATOR = "/"; const UA_NAME_ESCAPE_REGEX = /[^\!\$\%\&\'\*\+\-\.\^\_\`\|\~\d\w]/g; const UA_VALUE_ESCAPE_REGEX = /[^\!\$\%\&\'\*\+\-\.\^\_\`\|\~\d\w\#]/g; const UA_ESCAPE_CHAR = "-"; const BYTE_LIMIT = 1024; function encodeFeatures(features) { let buffer = ""; for (const key in features) { const val = features[key]; if (buffer.length + val.length + 1 <= BYTE_LIMIT) { if (buffer.length) { buffer += "," + val; } else { buffer += val; } continue; } break; } return buffer; } const userAgentMiddleware = (options) => (next, context) => async (args) => { const { request } = args; if (!protocolHttp.HttpRequest.isInstance(request)) { return next(args); } const { headers } = request; const userAgent = context?.userAgent?.map(escapeUserAgent) || []; const defaultUserAgent = (await options.defaultUserAgentProvider()).map(escapeUserAgent); await checkFeatures(context, options, args); const awsContext = context; defaultUserAgent.push(`m/${encodeFeatures(Object.assign({}, context.__smithy_context?.features, awsContext.__aws_sdk_context?.features))}`); const customUserAgent = options?.customUserAgent?.map(escapeUserAgent) || []; const appId = await options.userAgentAppId(); if (appId) { defaultUserAgent.push(escapeUserAgent([`app/${appId}`])); } const prefix = utilEndpoints.getUserAgentPrefix(); const sdkUserAgentValue = (prefix ? [prefix] : []) .concat([...defaultUserAgent, ...userAgent, ...customUserAgent]) .join(SPACE); const normalUAValue = [ ...defaultUserAgent.filter((section) => section.startsWith("aws-sdk-")), ...customUserAgent, ].join(SPACE); if (options.runtime !== "browser") { if (normalUAValue) { headers[X_AMZ_USER_AGENT] = headers[X_AMZ_USER_AGENT] ? `${headers[USER_AGENT]} ${normalUAValue}` : normalUAValue; } headers[USER_AGENT] = sdkUserAgentValue; } else { headers[X_AMZ_USER_AGENT] = sdkUserAgentValue; } return next({ ...args, request, }); }; const escapeUserAgent = (userAgentPair) => { const name = userAgentPair[0] .split(UA_NAME_SEPARATOR) .map((part) => part.replace(UA_NAME_ESCAPE_REGEX, UA_ESCAPE_CHAR)) .join(UA_NAME_SEPARATOR); const version = userAgentPair[1]?.replace(UA_VALUE_ESCAPE_REGEX, UA_ESCAPE_CHAR); const prefixSeparatorIndex = name.indexOf(UA_NAME_SEPARATOR); const prefix = name.substring(0, prefixSeparatorIndex); let uaName = name.substring(prefixSeparatorIndex + 1); if (prefix === "api") { uaName = uaName.toLowerCase(); } return [prefix, uaName, version] .filter((item) => item && item.length > 0) .reduce((acc, item, index) => { switch (index) { case 0: return item; case 1: return `${acc}/${item}`; default: return `${acc}#${item}`; } }, ""); }; const getUserAgentMiddlewareOptions = { name: "getUserAgentMiddleware", step: "build", priority: "low", tags: ["SET_USER_AGENT", "USER_AGENT"], override: true, }; const getUserAgentPlugin = (config) => ({ applyToStack: (clientStack) => { clientStack.add(userAgentMiddleware(config), getUserAgentMiddlewareOptions); }, }); exports.DEFAULT_UA_APP_ID = DEFAULT_UA_APP_ID; exports.getUserAgentMiddlewareOptions = getUserAgentMiddlewareOptions; exports.getUserAgentPlugin = getUserAgentPlugin; exports.resolveUserAgentConfig = resolveUserAgentConfig; exports.userAgentMiddleware = userAgentMiddleware;