All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.amazon.awssdk.regions.internal.util.HttpResourcesUtils Maven / Gradle / Ivy

Go to download

A single bundled dependency that includes all service and dependent JARs with third-party libraries relocated to different namespaces.

There is a newer version: 2.5.20
Show newest version
/*
 * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package software.amazon.awssdk.regions.internal.util;

import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.annotations.SdkProtectedApi;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.exception.SdkServiceException;
import software.amazon.awssdk.core.util.json.JacksonUtils;
import software.amazon.awssdk.utils.IoUtils;

@SdkInternalApi
@SdkProtectedApi
public final class HttpResourcesUtils {

    private static final Logger log = LoggerFactory.getLogger(HttpResourcesUtils.class);

    private static volatile HttpResourcesUtils instance;

    private final ConnectionUtils connectionUtils;

    private HttpResourcesUtils() {
        this(ConnectionUtils.create());
    }

    HttpResourcesUtils(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }

    public static HttpResourcesUtils instance() {
        if (instance == null) {
            synchronized (HttpResourcesUtils.class) {
                if (instance == null) {
                    instance = new HttpResourcesUtils();
                }
            }
        }
        return instance;
    }

    /**
     * Connects to the given endpoint to read the resource
     * and returns the text contents.
     *
     * If the connection fails, the request will not be retried.
     *
     * @param endpoint The service endpoint to connect to.
     * @return The text payload returned from the container metadata endpoint
     * service for the specified resource path.
     * @throws IOException If any problems were encountered while connecting to the
     * service for the requested resource path.
     * @throws SdkClientException If the requested service is not found.
     */
    public String readResource(URI endpoint) throws IOException {
        return readResource(() -> endpoint);
    }

    /**
     * Connects to the given endpoint to read the resource
     * and returns the text contents.
     *
     * @param endpointProvider The endpoint provider.
     * @return The text payload returned from the container metadata endpoint
     * service for the specified resource path.
     * @throws IOException If any problems were encountered while connecting to the
     * service for the requested resource path.
     * @throws SdkClientException If the requested service is not found.
     */
    public String readResource(ResourcesEndpointProvider endpointProvider) throws IOException {
        int retriesAttempted = 0;
        InputStream inputStream = null;

        while (true) {
            try {
                HttpURLConnection connection = connectionUtils.connectToEndpoint(endpointProvider.endpoint(),
                                                                                 endpointProvider.headers());

                int statusCode = connection.getResponseCode();

                if (statusCode == HttpURLConnection.HTTP_OK) {
                    inputStream = connection.getInputStream();
                    return IoUtils.toUtf8String(inputStream);
                } else if (statusCode == HttpURLConnection.HTTP_NOT_FOUND) {
                    // This is to preserve existing behavior of EC2 Instance metadata service.
                    throw SdkClientException.builder()
                                            .message("The requested metadata is not found at " + connection.getURL())
                                            .build();
                } else {
                    if (!endpointProvider.retryPolicy().shouldRetry(retriesAttempted++,
                                                                    ResourcesEndpointRetryParameters.builder()
                                                                                                    .withStatusCode(statusCode)
                                                                                                    .build())) {
                        inputStream = connection.getErrorStream();
                        handleErrorResponse(inputStream, statusCode, connection.getResponseMessage());
                    }
                }
            } catch (IOException ioException) {
                if (!endpointProvider.retryPolicy().shouldRetry(retriesAttempted++,
                                                                ResourcesEndpointRetryParameters.builder()
                                                                                                .withException(ioException)
                                                                                                .build())) {
                    throw ioException;
                }
                log.debug("An IOException occurred when connecting to endpoint: {} \n Retrying to connect again",
                          endpointProvider.endpoint());

            } finally {
                IoUtils.closeQuietly(inputStream, log);
            }
        }

    }

    private void handleErrorResponse(InputStream errorStream, int statusCode, String responseMessage) throws IOException {
        // Parse the error stream returned from the service.
        if (errorStream != null) {
            String errorResponse = IoUtils.toUtf8String(errorStream);

            try {
                JsonNode node = JacksonUtils.jsonNodeOf(errorResponse);
                JsonNode code = node.get("code");
                JsonNode message = node.get("message");
                if (code != null && message != null) {
                    responseMessage = message.asText();
                }
            } catch (RuntimeException exception) {
                log.debug("Unable to parse error stream", exception);
            }
        }

        SdkServiceException exception = SdkServiceException.builder()
                                                           .message(responseMessage)
                                                           .statusCode(statusCode)
                                                           .build();
        throw exception;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy