241 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
var getEndpointFromConfig = require('./adaptors/getEndpointFromConfig');
 | 
						|
var urlParser = require('@smithy/url-parser');
 | 
						|
var core = require('@smithy/core');
 | 
						|
var utilMiddleware = require('@smithy/util-middleware');
 | 
						|
var middlewareSerde = require('@smithy/middleware-serde');
 | 
						|
 | 
						|
const resolveParamsForS3 = async (endpointParams) => {
 | 
						|
    const bucket = endpointParams?.Bucket || "";
 | 
						|
    if (typeof endpointParams.Bucket === "string") {
 | 
						|
        endpointParams.Bucket = bucket.replace(/#/g, encodeURIComponent("#")).replace(/\?/g, encodeURIComponent("?"));
 | 
						|
    }
 | 
						|
    if (isArnBucketName(bucket)) {
 | 
						|
        if (endpointParams.ForcePathStyle === true) {
 | 
						|
            throw new Error("Path-style addressing cannot be used with ARN buckets");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else if (!isDnsCompatibleBucketName(bucket) ||
 | 
						|
        (bucket.indexOf(".") !== -1 && !String(endpointParams.Endpoint).startsWith("http:")) ||
 | 
						|
        bucket.toLowerCase() !== bucket ||
 | 
						|
        bucket.length < 3) {
 | 
						|
        endpointParams.ForcePathStyle = true;
 | 
						|
    }
 | 
						|
    if (endpointParams.DisableMultiRegionAccessPoints) {
 | 
						|
        endpointParams.disableMultiRegionAccessPoints = true;
 | 
						|
        endpointParams.DisableMRAP = true;
 | 
						|
    }
 | 
						|
    return endpointParams;
 | 
						|
};
 | 
						|
const DOMAIN_PATTERN = /^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/;
 | 
						|
const IP_ADDRESS_PATTERN = /(\d+\.){3}\d+/;
 | 
						|
const DOTS_PATTERN = /\.\./;
 | 
						|
const isDnsCompatibleBucketName = (bucketName) => DOMAIN_PATTERN.test(bucketName) && !IP_ADDRESS_PATTERN.test(bucketName) && !DOTS_PATTERN.test(bucketName);
 | 
						|
const isArnBucketName = (bucketName) => {
 | 
						|
    const [arn, partition, service, , , bucket] = bucketName.split(":");
 | 
						|
    const isArn = arn === "arn" && bucketName.split(":").length >= 6;
 | 
						|
    const isValidArn = Boolean(isArn && partition && service && bucket);
 | 
						|
    if (isArn && !isValidArn) {
 | 
						|
        throw new Error(`Invalid ARN: ${bucketName} was an invalid ARN.`);
 | 
						|
    }
 | 
						|
    return isValidArn;
 | 
						|
};
 | 
						|
 | 
						|
const createConfigValueProvider = (configKey, canonicalEndpointParamKey, config) => {
 | 
						|
    const configProvider = async () => {
 | 
						|
        const configValue = config[configKey] ?? config[canonicalEndpointParamKey];
 | 
						|
        if (typeof configValue === "function") {
 | 
						|
            return configValue();
 | 
						|
        }
 | 
						|
        return configValue;
 | 
						|
    };
 | 
						|
    if (configKey === "credentialScope" || canonicalEndpointParamKey === "CredentialScope") {
 | 
						|
        return async () => {
 | 
						|
            const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials;
 | 
						|
            const configValue = credentials?.credentialScope ?? credentials?.CredentialScope;
 | 
						|
            return configValue;
 | 
						|
        };
 | 
						|
    }
 | 
						|
    if (configKey === "accountId" || canonicalEndpointParamKey === "AccountId") {
 | 
						|
        return async () => {
 | 
						|
            const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials;
 | 
						|
            const configValue = credentials?.accountId ?? credentials?.AccountId;
 | 
						|
            return configValue;
 | 
						|
        };
 | 
						|
    }
 | 
						|
    if (configKey === "endpoint" || canonicalEndpointParamKey === "endpoint") {
 | 
						|
        return async () => {
 | 
						|
            if (config.isCustomEndpoint === false) {
 | 
						|
                return undefined;
 | 
						|
            }
 | 
						|
            const endpoint = await configProvider();
 | 
						|
            if (endpoint && typeof endpoint === "object") {
 | 
						|
                if ("url" in endpoint) {
 | 
						|
                    return endpoint.url.href;
 | 
						|
                }
 | 
						|
                if ("hostname" in endpoint) {
 | 
						|
                    const { protocol, hostname, port, path } = endpoint;
 | 
						|
                    return `${protocol}//${hostname}${port ? ":" + port : ""}${path}`;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return endpoint;
 | 
						|
        };
 | 
						|
    }
 | 
						|
    return configProvider;
 | 
						|
};
 | 
						|
 | 
						|
const toEndpointV1 = (endpoint) => {
 | 
						|
    if (typeof endpoint === "object") {
 | 
						|
        if ("url" in endpoint) {
 | 
						|
            return urlParser.parseUrl(endpoint.url);
 | 
						|
        }
 | 
						|
        return endpoint;
 | 
						|
    }
 | 
						|
    return urlParser.parseUrl(endpoint);
 | 
						|
};
 | 
						|
 | 
						|
const getEndpointFromInstructions = async (commandInput, instructionsSupplier, clientConfig, context) => {
 | 
						|
    if (!clientConfig.isCustomEndpoint) {
 | 
						|
        let endpointFromConfig;
 | 
						|
        if (clientConfig.serviceConfiguredEndpoint) {
 | 
						|
            endpointFromConfig = await clientConfig.serviceConfiguredEndpoint();
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            endpointFromConfig = await getEndpointFromConfig.getEndpointFromConfig(clientConfig.serviceId);
 | 
						|
        }
 | 
						|
        if (endpointFromConfig) {
 | 
						|
            clientConfig.endpoint = () => Promise.resolve(toEndpointV1(endpointFromConfig));
 | 
						|
            clientConfig.isCustomEndpoint = true;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    const endpointParams = await resolveParams(commandInput, instructionsSupplier, clientConfig);
 | 
						|
    if (typeof clientConfig.endpointProvider !== "function") {
 | 
						|
        throw new Error("config.endpointProvider is not set.");
 | 
						|
    }
 | 
						|
    const endpoint = clientConfig.endpointProvider(endpointParams, context);
 | 
						|
    return endpoint;
 | 
						|
};
 | 
						|
const resolveParams = async (commandInput, instructionsSupplier, clientConfig) => {
 | 
						|
    const endpointParams = {};
 | 
						|
    const instructions = instructionsSupplier?.getEndpointParameterInstructions?.() || {};
 | 
						|
    for (const [name, instruction] of Object.entries(instructions)) {
 | 
						|
        switch (instruction.type) {
 | 
						|
            case "staticContextParams":
 | 
						|
                endpointParams[name] = instruction.value;
 | 
						|
                break;
 | 
						|
            case "contextParams":
 | 
						|
                endpointParams[name] = commandInput[instruction.name];
 | 
						|
                break;
 | 
						|
            case "clientContextParams":
 | 
						|
            case "builtInParams":
 | 
						|
                endpointParams[name] = await createConfigValueProvider(instruction.name, name, clientConfig)();
 | 
						|
                break;
 | 
						|
            case "operationContextParams":
 | 
						|
                endpointParams[name] = instruction.get(commandInput);
 | 
						|
                break;
 | 
						|
            default:
 | 
						|
                throw new Error("Unrecognized endpoint parameter instruction: " + JSON.stringify(instruction));
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (Object.keys(instructions).length === 0) {
 | 
						|
        Object.assign(endpointParams, clientConfig);
 | 
						|
    }
 | 
						|
    if (String(clientConfig.serviceId).toLowerCase() === "s3") {
 | 
						|
        await resolveParamsForS3(endpointParams);
 | 
						|
    }
 | 
						|
    return endpointParams;
 | 
						|
};
 | 
						|
 | 
						|
const endpointMiddleware = ({ config, instructions, }) => {
 | 
						|
    return (next, context) => async (args) => {
 | 
						|
        if (config.isCustomEndpoint) {
 | 
						|
            core.setFeature(context, "ENDPOINT_OVERRIDE", "N");
 | 
						|
        }
 | 
						|
        const endpoint = await getEndpointFromInstructions(args.input, {
 | 
						|
            getEndpointParameterInstructions() {
 | 
						|
                return instructions;
 | 
						|
            },
 | 
						|
        }, { ...config }, context);
 | 
						|
        context.endpointV2 = endpoint;
 | 
						|
        context.authSchemes = endpoint.properties?.authSchemes;
 | 
						|
        const authScheme = context.authSchemes?.[0];
 | 
						|
        if (authScheme) {
 | 
						|
            context["signing_region"] = authScheme.signingRegion;
 | 
						|
            context["signing_service"] = authScheme.signingName;
 | 
						|
            const smithyContext = utilMiddleware.getSmithyContext(context);
 | 
						|
            const httpAuthOption = smithyContext?.selectedHttpAuthScheme?.httpAuthOption;
 | 
						|
            if (httpAuthOption) {
 | 
						|
                httpAuthOption.signingProperties = Object.assign(httpAuthOption.signingProperties || {}, {
 | 
						|
                    signing_region: authScheme.signingRegion,
 | 
						|
                    signingRegion: authScheme.signingRegion,
 | 
						|
                    signing_service: authScheme.signingName,
 | 
						|
                    signingName: authScheme.signingName,
 | 
						|
                    signingRegionSet: authScheme.signingRegionSet,
 | 
						|
                }, authScheme.properties);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return next({
 | 
						|
            ...args,
 | 
						|
        });
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
const endpointMiddlewareOptions = {
 | 
						|
    step: "serialize",
 | 
						|
    tags: ["ENDPOINT_PARAMETERS", "ENDPOINT_V2", "ENDPOINT"],
 | 
						|
    name: "endpointV2Middleware",
 | 
						|
    override: true,
 | 
						|
    relation: "before",
 | 
						|
    toMiddleware: middlewareSerde.serializerMiddlewareOption.name,
 | 
						|
};
 | 
						|
const getEndpointPlugin = (config, instructions) => ({
 | 
						|
    applyToStack: (clientStack) => {
 | 
						|
        clientStack.addRelativeTo(endpointMiddleware({
 | 
						|
            config,
 | 
						|
            instructions,
 | 
						|
        }), endpointMiddlewareOptions);
 | 
						|
    },
 | 
						|
});
 | 
						|
 | 
						|
const resolveEndpointConfig = (input) => {
 | 
						|
    const tls = input.tls ?? true;
 | 
						|
    const { endpoint, useDualstackEndpoint, useFipsEndpoint } = input;
 | 
						|
    const customEndpointProvider = endpoint != null ? async () => toEndpointV1(await utilMiddleware.normalizeProvider(endpoint)()) : undefined;
 | 
						|
    const isCustomEndpoint = !!endpoint;
 | 
						|
    const resolvedConfig = Object.assign(input, {
 | 
						|
        endpoint: customEndpointProvider,
 | 
						|
        tls,
 | 
						|
        isCustomEndpoint,
 | 
						|
        useDualstackEndpoint: utilMiddleware.normalizeProvider(useDualstackEndpoint ?? false),
 | 
						|
        useFipsEndpoint: utilMiddleware.normalizeProvider(useFipsEndpoint ?? false),
 | 
						|
    });
 | 
						|
    let configuredEndpointPromise = undefined;
 | 
						|
    resolvedConfig.serviceConfiguredEndpoint = async () => {
 | 
						|
        if (input.serviceId && !configuredEndpointPromise) {
 | 
						|
            configuredEndpointPromise = getEndpointFromConfig.getEndpointFromConfig(input.serviceId);
 | 
						|
        }
 | 
						|
        return configuredEndpointPromise;
 | 
						|
    };
 | 
						|
    return resolvedConfig;
 | 
						|
};
 | 
						|
 | 
						|
const resolveEndpointRequiredConfig = (input) => {
 | 
						|
    const { endpoint } = input;
 | 
						|
    if (endpoint === undefined) {
 | 
						|
        input.endpoint = async () => {
 | 
						|
            throw new Error("@smithy/middleware-endpoint: (default endpointRuleSet) endpoint is not set - you must configure an endpoint.");
 | 
						|
        };
 | 
						|
    }
 | 
						|
    return input;
 | 
						|
};
 | 
						|
 | 
						|
exports.endpointMiddleware = endpointMiddleware;
 | 
						|
exports.endpointMiddlewareOptions = endpointMiddlewareOptions;
 | 
						|
exports.getEndpointFromInstructions = getEndpointFromInstructions;
 | 
						|
exports.getEndpointPlugin = getEndpointPlugin;
 | 
						|
exports.resolveEndpointConfig = resolveEndpointConfig;
 | 
						|
exports.resolveEndpointRequiredConfig = resolveEndpointRequiredConfig;
 | 
						|
exports.resolveParams = resolveParams;
 | 
						|
exports.toEndpointV1 = toEndpointV1;
 |