private MethodSpec modifyRequestMethod()

in codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java [177:270]


    private MethodSpec modifyRequestMethod(String endpointAuthSchemeStrategyFieldName) {

        MethodSpec.Builder b = MethodSpec.methodBuilder("modifyRequest")
                                         .addModifiers(Modifier.PUBLIC)
                                         .addAnnotation(Override.class)
                                         .returns(SdkRequest.class)
                                         .addParameter(Context.ModifyRequest.class, "context")
                                         .addParameter(ExecutionAttributes.class, "executionAttributes");

        String providerVar = "provider";

        b.addStatement("$T result = context.request()", SdkRequest.class);
        // We skip resolution if the source of the endpoint is the endpoint discovery call
        b.beginControlFlow("if ($1T.endpointIsDiscovered(executionAttributes))",
                           endpointRulesSpecUtils.rulesRuntimeClassName("AwsEndpointProviderUtils"));
        b.addStatement("return result");
        b.endControlFlow();

        b.addStatement("$1T $2N = ($1T) executionAttributes.getAttribute($3T.ENDPOINT_PROVIDER)",
                       endpointRulesSpecUtils.providerInterfaceName(), providerVar, SdkInternalExecutionAttribute.class);
        b.beginControlFlow("try");
        b.addStatement("long resolveEndpointStart = $T.nanoTime()", System.class);
        b.addStatement("$T endpointParams = ruleParams(result, executionAttributes)",
                       endpointRulesSpecUtils.parametersClassName());
        b.addStatement("$T endpoint = $N.resolveEndpoint(endpointParams).join()",
                       Endpoint.class, providerVar);
        b.addStatement("$1T resolveEndpointDuration = $1T.ofNanos($2T.nanoTime() - resolveEndpointStart)", Duration.class,
                       System.class);
        b.addStatement("$T metricCollector = executionAttributes.getOptionalAttribute($T.API_CALL_METRIC_COLLECTOR)",
                       ParameterizedTypeName.get(Optional.class, MetricCollector.class), SdkExecutionAttribute.class);
        b.addStatement("metricCollector.ifPresent(mc -> mc.reportMetric($T.ENDPOINT_RESOLVE_DURATION, resolveEndpointDuration))",
                       CoreMetric.class);
        b.beginControlFlow("if (!$T.disableHostPrefixInjection(executionAttributes))",
                           endpointRulesSpecUtils.rulesRuntimeClassName("AwsEndpointProviderUtils"));
        b.addStatement("$T hostPrefix = hostPrefix(executionAttributes.getAttribute($T.OPERATION_NAME), result)",
                       ParameterizedTypeName.get(Optional.class, String.class), SdkExecutionAttribute.class);
        b.beginControlFlow("if (hostPrefix.isPresent())");
        b.addStatement("endpoint = $T.addHostPrefix(endpoint, hostPrefix.get())",
                       endpointRulesSpecUtils.rulesRuntimeClassName("AwsEndpointProviderUtils"));
        b.endControlFlow();
        b.endControlFlow();


        // If the endpoint resolver returns auth settings, use them as signer properties.
        // This effectively works to set the preSRA Signer ExecutionAttributes, so it is not conditional on useSraAuth.
        b.addStatement("$T<$T> endpointAuthSchemes = endpoint.attribute($T.AUTH_SCHEMES)",
                       List.class, EndpointAuthScheme.class, AwsEndpointAttribute.class);
        b.addStatement("$T<?> selectedAuthScheme = executionAttributes.getAttribute($T.SELECTED_AUTH_SCHEME)",
                       SelectedAuthScheme.class, SdkInternalExecutionAttribute.class);
        b.beginControlFlow("if (endpointAuthSchemes != null && selectedAuthScheme != null)");
        b.addStatement("selectedAuthScheme = authSchemeWithEndpointSignerProperties(endpointAuthSchemes, selectedAuthScheme)");
        if (multiAuthSigv4a || legacyAuthFromEndpointRulesService) {
            b.addComment("Precedence of SigV4a RegionSet is set according to multi-auth SigV4a specifications");
            b.beginControlFlow("if(selectedAuthScheme.authSchemeOption().schemeId().equals($T.SCHEME_ID) "
                               + "&& selectedAuthScheme.authSchemeOption().signerProperty($T.REGION_SET) == null)",
                               AwsV4aAuthScheme.class, AwsV4aHttpSigner.class);
            b.addStatement("$T optionBuilder = selectedAuthScheme.authSchemeOption().toBuilder()",
                           AuthSchemeOption.Builder.class);
            b.addStatement("$T regionSet = $T.create(endpointParams.region().id())",
                           RegionSet.class, RegionSet.class);
            b.addStatement("optionBuilder.putSignerProperty($T.REGION_SET, regionSet)", AwsV4aHttpSigner.class);
            b.addStatement("selectedAuthScheme = new $T(selectedAuthScheme.identity(), selectedAuthScheme.signer(), "
                           + "optionBuilder.build())", SelectedAuthScheme.class);
            b.endControlFlow();
        }
        b.addStatement("executionAttributes.putAttribute($T.SELECTED_AUTH_SCHEME, selectedAuthScheme)",
                       SdkInternalExecutionAttribute.class);
        b.endControlFlow();

        // For pre SRA client, use Signer as determined by endpoint resolved auth scheme
        if (!useSraAuth) {
            b.beginControlFlow("if (endpointAuthSchemes != null)");
            b.addStatement("$T chosenAuthScheme = $N.chooseAuthScheme(endpointAuthSchemes)", EndpointAuthScheme.class,
                           endpointAuthSchemeStrategyFieldName);
            b.addStatement("$T<$T> signerProvider = signerProvider(chosenAuthScheme)", Supplier.class, Signer.class);
            b.addStatement("result = $T.overrideSignerIfNotOverridden(result, executionAttributes, signerProvider)",
                           SignerOverrideUtils.class);
            b.endControlFlow();
        }

        b.addStatement("executionAttributes.putAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT, endpoint)");
        b.addStatement("return result");
        b.endControlFlow();
        b.beginControlFlow("catch ($T e)", CompletionException.class);
        b.addStatement("$T cause = e.getCause()", Throwable.class);
        b.beginControlFlow("if (cause instanceof $T)", SdkClientException.class);
        b.addStatement("throw ($T) cause", SdkClientException.class);
        b.endControlFlow();
        b.beginControlFlow("else");
        b.addStatement("throw $T.create($S, cause)", SdkClientException.class, "Endpoint resolution failed");
        b.endControlFlow();
        b.endControlFlow();
        return b.build();
    }