350 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			350 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
var types = require('@smithy/types');
 | 
						|
var utilMiddleware = require('@smithy/util-middleware');
 | 
						|
var middlewareSerde = require('@smithy/middleware-serde');
 | 
						|
var protocolHttp = require('@smithy/protocol-http');
 | 
						|
var protocols = require('@smithy/core/protocols');
 | 
						|
 | 
						|
const getSmithyContext = (context) => context[types.SMITHY_CONTEXT_KEY] || (context[types.SMITHY_CONTEXT_KEY] = {});
 | 
						|
 | 
						|
const resolveAuthOptions = (candidateAuthOptions, authSchemePreference) => {
 | 
						|
    if (!authSchemePreference || authSchemePreference.length === 0) {
 | 
						|
        return candidateAuthOptions;
 | 
						|
    }
 | 
						|
    const preferredAuthOptions = [];
 | 
						|
    for (const preferredSchemeName of authSchemePreference) {
 | 
						|
        for (const candidateAuthOption of candidateAuthOptions) {
 | 
						|
            const candidateAuthSchemeName = candidateAuthOption.schemeId.split("#")[1];
 | 
						|
            if (candidateAuthSchemeName === preferredSchemeName) {
 | 
						|
                preferredAuthOptions.push(candidateAuthOption);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    for (const candidateAuthOption of candidateAuthOptions) {
 | 
						|
        if (!preferredAuthOptions.find(({ schemeId }) => schemeId === candidateAuthOption.schemeId)) {
 | 
						|
            preferredAuthOptions.push(candidateAuthOption);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return preferredAuthOptions;
 | 
						|
};
 | 
						|
 | 
						|
function convertHttpAuthSchemesToMap(httpAuthSchemes) {
 | 
						|
    const map = new Map();
 | 
						|
    for (const scheme of httpAuthSchemes) {
 | 
						|
        map.set(scheme.schemeId, scheme);
 | 
						|
    }
 | 
						|
    return map;
 | 
						|
}
 | 
						|
const httpAuthSchemeMiddleware = (config, mwOptions) => (next, context) => async (args) => {
 | 
						|
    const options = config.httpAuthSchemeProvider(await mwOptions.httpAuthSchemeParametersProvider(config, context, args.input));
 | 
						|
    const authSchemePreference = config.authSchemePreference ? await config.authSchemePreference() : [];
 | 
						|
    const resolvedOptions = resolveAuthOptions(options, authSchemePreference);
 | 
						|
    const authSchemes = convertHttpAuthSchemesToMap(config.httpAuthSchemes);
 | 
						|
    const smithyContext = utilMiddleware.getSmithyContext(context);
 | 
						|
    const failureReasons = [];
 | 
						|
    for (const option of resolvedOptions) {
 | 
						|
        const scheme = authSchemes.get(option.schemeId);
 | 
						|
        if (!scheme) {
 | 
						|
            failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` was not enabled for this service.`);
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        const identityProvider = scheme.identityProvider(await mwOptions.identityProviderConfigProvider(config));
 | 
						|
        if (!identityProvider) {
 | 
						|
            failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` did not have an IdentityProvider configured.`);
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        const { identityProperties = {}, signingProperties = {} } = option.propertiesExtractor?.(config, context) || {};
 | 
						|
        option.identityProperties = Object.assign(option.identityProperties || {}, identityProperties);
 | 
						|
        option.signingProperties = Object.assign(option.signingProperties || {}, signingProperties);
 | 
						|
        smithyContext.selectedHttpAuthScheme = {
 | 
						|
            httpAuthOption: option,
 | 
						|
            identity: await identityProvider(option.identityProperties),
 | 
						|
            signer: scheme.signer,
 | 
						|
        };
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    if (!smithyContext.selectedHttpAuthScheme) {
 | 
						|
        throw new Error(failureReasons.join("\n"));
 | 
						|
    }
 | 
						|
    return next(args);
 | 
						|
};
 | 
						|
 | 
						|
const httpAuthSchemeEndpointRuleSetMiddlewareOptions = {
 | 
						|
    step: "serialize",
 | 
						|
    tags: ["HTTP_AUTH_SCHEME"],
 | 
						|
    name: "httpAuthSchemeMiddleware",
 | 
						|
    override: true,
 | 
						|
    relation: "before",
 | 
						|
    toMiddleware: "endpointV2Middleware",
 | 
						|
};
 | 
						|
const getHttpAuthSchemeEndpointRuleSetPlugin = (config, { httpAuthSchemeParametersProvider, identityProviderConfigProvider, }) => ({
 | 
						|
    applyToStack: (clientStack) => {
 | 
						|
        clientStack.addRelativeTo(httpAuthSchemeMiddleware(config, {
 | 
						|
            httpAuthSchemeParametersProvider,
 | 
						|
            identityProviderConfigProvider,
 | 
						|
        }), httpAuthSchemeEndpointRuleSetMiddlewareOptions);
 | 
						|
    },
 | 
						|
});
 | 
						|
 | 
						|
const httpAuthSchemeMiddlewareOptions = {
 | 
						|
    step: "serialize",
 | 
						|
    tags: ["HTTP_AUTH_SCHEME"],
 | 
						|
    name: "httpAuthSchemeMiddleware",
 | 
						|
    override: true,
 | 
						|
    relation: "before",
 | 
						|
    toMiddleware: middlewareSerde.serializerMiddlewareOption.name,
 | 
						|
};
 | 
						|
const getHttpAuthSchemePlugin = (config, { httpAuthSchemeParametersProvider, identityProviderConfigProvider, }) => ({
 | 
						|
    applyToStack: (clientStack) => {
 | 
						|
        clientStack.addRelativeTo(httpAuthSchemeMiddleware(config, {
 | 
						|
            httpAuthSchemeParametersProvider,
 | 
						|
            identityProviderConfigProvider,
 | 
						|
        }), httpAuthSchemeMiddlewareOptions);
 | 
						|
    },
 | 
						|
});
 | 
						|
 | 
						|
const defaultErrorHandler = (signingProperties) => (error) => {
 | 
						|
    throw error;
 | 
						|
};
 | 
						|
const defaultSuccessHandler = (httpResponse, signingProperties) => { };
 | 
						|
const httpSigningMiddleware = (config) => (next, context) => async (args) => {
 | 
						|
    if (!protocolHttp.HttpRequest.isInstance(args.request)) {
 | 
						|
        return next(args);
 | 
						|
    }
 | 
						|
    const smithyContext = utilMiddleware.getSmithyContext(context);
 | 
						|
    const scheme = smithyContext.selectedHttpAuthScheme;
 | 
						|
    if (!scheme) {
 | 
						|
        throw new Error(`No HttpAuthScheme was selected: unable to sign request`);
 | 
						|
    }
 | 
						|
    const { httpAuthOption: { signingProperties = {} }, identity, signer, } = scheme;
 | 
						|
    const output = await next({
 | 
						|
        ...args,
 | 
						|
        request: await signer.sign(args.request, identity, signingProperties),
 | 
						|
    }).catch((signer.errorHandler || defaultErrorHandler)(signingProperties));
 | 
						|
    (signer.successHandler || defaultSuccessHandler)(output.response, signingProperties);
 | 
						|
    return output;
 | 
						|
};
 | 
						|
 | 
						|
const httpSigningMiddlewareOptions = {
 | 
						|
    step: "finalizeRequest",
 | 
						|
    tags: ["HTTP_SIGNING"],
 | 
						|
    name: "httpSigningMiddleware",
 | 
						|
    aliases: ["apiKeyMiddleware", "tokenMiddleware", "awsAuthMiddleware"],
 | 
						|
    override: true,
 | 
						|
    relation: "after",
 | 
						|
    toMiddleware: "retryMiddleware",
 | 
						|
};
 | 
						|
const getHttpSigningPlugin = (config) => ({
 | 
						|
    applyToStack: (clientStack) => {
 | 
						|
        clientStack.addRelativeTo(httpSigningMiddleware(), httpSigningMiddlewareOptions);
 | 
						|
    },
 | 
						|
});
 | 
						|
 | 
						|
const normalizeProvider = (input) => {
 | 
						|
    if (typeof input === "function")
 | 
						|
        return input;
 | 
						|
    const promisified = Promise.resolve(input);
 | 
						|
    return () => promisified;
 | 
						|
};
 | 
						|
 | 
						|
const makePagedClientRequest = async (CommandCtor, client, input, withCommand = (_) => _, ...args) => {
 | 
						|
    let command = new CommandCtor(input);
 | 
						|
    command = withCommand(command) ?? command;
 | 
						|
    return await client.send(command, ...args);
 | 
						|
};
 | 
						|
function createPaginator(ClientCtor, CommandCtor, inputTokenName, outputTokenName, pageSizeTokenName) {
 | 
						|
    return async function* paginateOperation(config, input, ...additionalArguments) {
 | 
						|
        const _input = input;
 | 
						|
        let token = config.startingToken ?? _input[inputTokenName];
 | 
						|
        let hasNext = true;
 | 
						|
        let page;
 | 
						|
        while (hasNext) {
 | 
						|
            _input[inputTokenName] = token;
 | 
						|
            if (pageSizeTokenName) {
 | 
						|
                _input[pageSizeTokenName] = _input[pageSizeTokenName] ?? config.pageSize;
 | 
						|
            }
 | 
						|
            if (config.client instanceof ClientCtor) {
 | 
						|
                page = await makePagedClientRequest(CommandCtor, config.client, input, config.withCommand, ...additionalArguments);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                throw new Error(`Invalid client, expected instance of ${ClientCtor.name}`);
 | 
						|
            }
 | 
						|
            yield page;
 | 
						|
            const prevToken = token;
 | 
						|
            token = get(page, outputTokenName);
 | 
						|
            hasNext = !!(token && (!config.stopOnSameToken || token !== prevToken));
 | 
						|
        }
 | 
						|
        return undefined;
 | 
						|
    };
 | 
						|
}
 | 
						|
const get = (fromObject, path) => {
 | 
						|
    let cursor = fromObject;
 | 
						|
    const pathComponents = path.split(".");
 | 
						|
    for (const step of pathComponents) {
 | 
						|
        if (!cursor || typeof cursor !== "object") {
 | 
						|
            return undefined;
 | 
						|
        }
 | 
						|
        cursor = cursor[step];
 | 
						|
    }
 | 
						|
    return cursor;
 | 
						|
};
 | 
						|
 | 
						|
function setFeature(context, feature, value) {
 | 
						|
    if (!context.__smithy_context) {
 | 
						|
        context.__smithy_context = {
 | 
						|
            features: {},
 | 
						|
        };
 | 
						|
    }
 | 
						|
    else if (!context.__smithy_context.features) {
 | 
						|
        context.__smithy_context.features = {};
 | 
						|
    }
 | 
						|
    context.__smithy_context.features[feature] = value;
 | 
						|
}
 | 
						|
 | 
						|
class DefaultIdentityProviderConfig {
 | 
						|
    authSchemes = new Map();
 | 
						|
    constructor(config) {
 | 
						|
        for (const [key, value] of Object.entries(config)) {
 | 
						|
            if (value !== undefined) {
 | 
						|
                this.authSchemes.set(key, value);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    getIdentityProvider(schemeId) {
 | 
						|
        return this.authSchemes.get(schemeId);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class HttpApiKeyAuthSigner {
 | 
						|
    async sign(httpRequest, identity, signingProperties) {
 | 
						|
        if (!signingProperties) {
 | 
						|
            throw new Error("request could not be signed with `apiKey` since the `name` and `in` signer properties are missing");
 | 
						|
        }
 | 
						|
        if (!signingProperties.name) {
 | 
						|
            throw new Error("request could not be signed with `apiKey` since the `name` signer property is missing");
 | 
						|
        }
 | 
						|
        if (!signingProperties.in) {
 | 
						|
            throw new Error("request could not be signed with `apiKey` since the `in` signer property is missing");
 | 
						|
        }
 | 
						|
        if (!identity.apiKey) {
 | 
						|
            throw new Error("request could not be signed with `apiKey` since the `apiKey` is not defined");
 | 
						|
        }
 | 
						|
        const clonedRequest = protocolHttp.HttpRequest.clone(httpRequest);
 | 
						|
        if (signingProperties.in === types.HttpApiKeyAuthLocation.QUERY) {
 | 
						|
            clonedRequest.query[signingProperties.name] = identity.apiKey;
 | 
						|
        }
 | 
						|
        else if (signingProperties.in === types.HttpApiKeyAuthLocation.HEADER) {
 | 
						|
            clonedRequest.headers[signingProperties.name] = signingProperties.scheme
 | 
						|
                ? `${signingProperties.scheme} ${identity.apiKey}`
 | 
						|
                : identity.apiKey;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            throw new Error("request can only be signed with `apiKey` locations `query` or `header`, " +
 | 
						|
                "but found: `" +
 | 
						|
                signingProperties.in +
 | 
						|
                "`");
 | 
						|
        }
 | 
						|
        return clonedRequest;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class HttpBearerAuthSigner {
 | 
						|
    async sign(httpRequest, identity, signingProperties) {
 | 
						|
        const clonedRequest = protocolHttp.HttpRequest.clone(httpRequest);
 | 
						|
        if (!identity.token) {
 | 
						|
            throw new Error("request could not be signed with `token` since the `token` is not defined");
 | 
						|
        }
 | 
						|
        clonedRequest.headers["Authorization"] = `Bearer ${identity.token}`;
 | 
						|
        return clonedRequest;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class NoAuthSigner {
 | 
						|
    async sign(httpRequest, identity, signingProperties) {
 | 
						|
        return httpRequest;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
const createIsIdentityExpiredFunction = (expirationMs) => function isIdentityExpired(identity) {
 | 
						|
    return doesIdentityRequireRefresh(identity) && identity.expiration.getTime() - Date.now() < expirationMs;
 | 
						|
};
 | 
						|
const EXPIRATION_MS = 300_000;
 | 
						|
const isIdentityExpired = createIsIdentityExpiredFunction(EXPIRATION_MS);
 | 
						|
const doesIdentityRequireRefresh = (identity) => identity.expiration !== undefined;
 | 
						|
const memoizeIdentityProvider = (provider, isExpired, requiresRefresh) => {
 | 
						|
    if (provider === undefined) {
 | 
						|
        return undefined;
 | 
						|
    }
 | 
						|
    const normalizedProvider = typeof provider !== "function" ? async () => Promise.resolve(provider) : provider;
 | 
						|
    let resolved;
 | 
						|
    let pending;
 | 
						|
    let hasResult;
 | 
						|
    let isConstant = false;
 | 
						|
    const coalesceProvider = async (options) => {
 | 
						|
        if (!pending) {
 | 
						|
            pending = normalizedProvider(options);
 | 
						|
        }
 | 
						|
        try {
 | 
						|
            resolved = await pending;
 | 
						|
            hasResult = true;
 | 
						|
            isConstant = false;
 | 
						|
        }
 | 
						|
        finally {
 | 
						|
            pending = undefined;
 | 
						|
        }
 | 
						|
        return resolved;
 | 
						|
    };
 | 
						|
    if (isExpired === undefined) {
 | 
						|
        return async (options) => {
 | 
						|
            if (!hasResult || options?.forceRefresh) {
 | 
						|
                resolved = await coalesceProvider(options);
 | 
						|
            }
 | 
						|
            return resolved;
 | 
						|
        };
 | 
						|
    }
 | 
						|
    return async (options) => {
 | 
						|
        if (!hasResult || options?.forceRefresh) {
 | 
						|
            resolved = await coalesceProvider(options);
 | 
						|
        }
 | 
						|
        if (isConstant) {
 | 
						|
            return resolved;
 | 
						|
        }
 | 
						|
        if (!requiresRefresh(resolved)) {
 | 
						|
            isConstant = true;
 | 
						|
            return resolved;
 | 
						|
        }
 | 
						|
        if (isExpired(resolved)) {
 | 
						|
            await coalesceProvider(options);
 | 
						|
            return resolved;
 | 
						|
        }
 | 
						|
        return resolved;
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
Object.defineProperty(exports, "requestBuilder", {
 | 
						|
    enumerable: true,
 | 
						|
    get: function () { return protocols.requestBuilder; }
 | 
						|
});
 | 
						|
exports.DefaultIdentityProviderConfig = DefaultIdentityProviderConfig;
 | 
						|
exports.EXPIRATION_MS = EXPIRATION_MS;
 | 
						|
exports.HttpApiKeyAuthSigner = HttpApiKeyAuthSigner;
 | 
						|
exports.HttpBearerAuthSigner = HttpBearerAuthSigner;
 | 
						|
exports.NoAuthSigner = NoAuthSigner;
 | 
						|
exports.createIsIdentityExpiredFunction = createIsIdentityExpiredFunction;
 | 
						|
exports.createPaginator = createPaginator;
 | 
						|
exports.doesIdentityRequireRefresh = doesIdentityRequireRefresh;
 | 
						|
exports.getHttpAuthSchemeEndpointRuleSetPlugin = getHttpAuthSchemeEndpointRuleSetPlugin;
 | 
						|
exports.getHttpAuthSchemePlugin = getHttpAuthSchemePlugin;
 | 
						|
exports.getHttpSigningPlugin = getHttpSigningPlugin;
 | 
						|
exports.getSmithyContext = getSmithyContext;
 | 
						|
exports.httpAuthSchemeEndpointRuleSetMiddlewareOptions = httpAuthSchemeEndpointRuleSetMiddlewareOptions;
 | 
						|
exports.httpAuthSchemeMiddleware = httpAuthSchemeMiddleware;
 | 
						|
exports.httpAuthSchemeMiddlewareOptions = httpAuthSchemeMiddlewareOptions;
 | 
						|
exports.httpSigningMiddleware = httpSigningMiddleware;
 | 
						|
exports.httpSigningMiddlewareOptions = httpSigningMiddlewareOptions;
 | 
						|
exports.isIdentityExpired = isIdentityExpired;
 | 
						|
exports.memoizeIdentityProvider = memoizeIdentityProvider;
 | 
						|
exports.normalizeProvider = normalizeProvider;
 | 
						|
exports.setFeature = setFeature;
 |