Search code examples
elasticsearchaws-lambdaaws-sdkamazon-elasticsearch

Unable to resolve AWSRequestSigningApacheInterceptor


Hi All i have downloaded the below code from AWS in order to index the data to my elasticsearch service but it has end up with error i am unable to build the code.

package com.Lambda.dynamodb;

import org.apache.http.HttpHost;
import org.apache.http.HttpRequestInterceptor;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import com.amazonaws.auth.AWS4Signer;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.http.AWSRequestSigningApacheInterceptor;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class AmazonElasticsearchServiceSample {

    private static String serviceName = "es";
    private static String region = "us-west-1";
    private static String aesEndpoint = ""; // e.g. https://search-mydomain.us-west-1.es.amazonaws.com
    private static String index = "my-index";
    private static String type = "_doc";
    private static String id = "1";

    static final AWSCredentialsProvider credentialsProvider = new DefaultAWSCredentialsProviderChain();

    public static void main(String[] args) throws IOException {
        RestHighLevelClient esClient = esClient(serviceName, region);

        // Create the document as a hash map
        Map<String, Object> document = new HashMap<>();
        document.put("title", "Walk the Line");
        document.put("director", "James Mangold");
        document.put("year", "2005");

        // Form the indexing request, send it, and print the response
        IndexRequest request = new IndexRequest(index, type, id).source(document);
        IndexResponse response = esClient.index(request, RequestOptions.DEFAULT);
        System.out.println(response.toString());
    }

    // Adds the interceptor to the ES REST client
    public static RestHighLevelClient esClient(String serviceName, String region) {
        AWS4Signer signer = new AWS4Signer();
        signer.setServiceName(serviceName);
        signer.setRegionName(region);
        HttpRequestInterceptor interceptor = new AWSRequestSigningApacheInterceptor(serviceName, signer, credentialsProvider);
        return new RestHighLevelClient(RestClient.builder(HttpHost.create(aesEndpoint)).setHttpClientConfigCallback(hacb -> hacb.addInterceptorLast(interceptor)));
    }
}

Error Cannot resolve AWSRequestSigningApacheInterceptor

I have tried multiple maven dependency but still it is not resolved

Could any one please suggest how to resolve this?


Solution

  • Create a class file and place this code. this will do the rest

    import com.amazonaws.auth.AWSCredentialsProvider;
    import com.amazonaws.auth.Signer;
    import com.amazonaws.http.HttpMethodName;
    import org.apache.http.Header;
    import org.apache.http.HttpEntityEnclosingRequest;
    import org.apache.http.HttpException;
    import org.apache.http.HttpHost;
    import org.apache.http.HttpRequest;
    import org.apache.http.HttpRequestInterceptor;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.utils.URIBuilder;
    import org.apache.http.entity.BasicHttpEntity;
    import org.apache.http.message.BasicHeader;
    import org.apache.http.protocol.HttpContext;
    
    import java.io.IOException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.TreeMap;
    
    import static org.apache.http.protocol.HttpCoreContext.HTTP_TARGET_HOST;
    
    /**
     * An {@link HttpRequestInterceptor} that signs requests using any AWS {@link Signer}
     * and {@link AWSCredentialsProvider}.
     */
    public class AWSRequestSigningApacheInterceptor implements HttpRequestInterceptor {
        /**
         * The service that we're connecting to. Technically not necessary.
         * Could be used by a future Signer, though.
         */
        private final String service;
    
        /**
         * The particular signer implementation.
         */
        private final Signer signer;
    
        /**
         * The source of AWS credentials for signing.
         */
        private final AWSCredentialsProvider awsCredentialsProvider;
    
        /**
         *
         * @param service service that we're connecting to
         * @param signer particular signer implementation
         * @param awsCredentialsProvider source of AWS credentials for signing
         */
        public AWSRequestSigningApacheInterceptor(final String service,
                                                  final Signer signer,
                                                  final AWSCredentialsProvider awsCredentialsProvider) {
            this.service = service;
            this.signer = signer;
            this.awsCredentialsProvider = awsCredentialsProvider;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public void process(final HttpRequest request, final HttpContext context)
                throws HttpException, IOException {
            URIBuilder uriBuilder;
            try {
                uriBuilder = new URIBuilder(request.getRequestLine().getUri());
            } catch (URISyntaxException e) {
                throw new IOException("Invalid URI" , e);
            }
    
            // Copy Apache HttpRequest to AWS DefaultRequest
            DefaultRequest<?> signableRequest = new DefaultRequest<>(service);
    
            HttpHost host = (HttpHost) context.getAttribute(HTTP_TARGET_HOST);
            if (host != null) {
                signableRequest.setEndpoint(URI.create(host.toURI()));
            }
            final HttpMethodName httpMethod =
                    HttpMethodName.fromValue(request.getRequestLine().getMethod());
            signableRequest.setHttpMethod(httpMethod);
            try {
                signableRequest.setResourcePath(uriBuilder.build().getRawPath());
            } catch (URISyntaxException e) {
                throw new IOException("Invalid URI" , e);
            }
    
            if (request instanceof HttpEntityEnclosingRequest) {
                HttpEntityEnclosingRequest httpEntityEnclosingRequest =
                        (HttpEntityEnclosingRequest) request;
                if (httpEntityEnclosingRequest.getEntity() != null) {
                    signableRequest.setContent(httpEntityEnclosingRequest.getEntity().getContent());
                }
            }
            signableRequest.setParameters(nvpToMapParams(uriBuilder.getQueryParams()));
            signableRequest.setHeaders(headerArrayToMap(request.getAllHeaders()));
    
            // Sign it
            signer.sign(signableRequest, awsCredentialsProvider.getCredentials());
    
            // Now copy everything back
            request.setHeaders(mapToHeaderArray(signableRequest.getHeaders()));
            if (request instanceof HttpEntityEnclosingRequest) {
                HttpEntityEnclosingRequest httpEntityEnclosingRequest =
                        (HttpEntityEnclosingRequest) request;
                if (httpEntityEnclosingRequest.getEntity() != null) {
                    BasicHttpEntity basicHttpEntity = new BasicHttpEntity();
                    basicHttpEntity.setContent(signableRequest.getContent());
                    httpEntityEnclosingRequest.setEntity(basicHttpEntity);
                }
            }
        }
    
        /**
         *
         * @param params list of HTTP query params as NameValuePairs
         * @return a multimap of HTTP query params
         */
        private static Map<String, List<String>> nvpToMapParams(final List<NameValuePair> params) {
            Map<String, List<String>> parameterMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
            for (NameValuePair nvp : params) {
                List<String> argsList =
                        parameterMap.computeIfAbsent(nvp.getName(), k -> new ArrayList<>());
                argsList.add(nvp.getValue());
            }
            return parameterMap;
        }
    
        /**
         * @param headers modeled Header objects
         * @return a Map of header entries
         */
        private static Map<String, String> headerArrayToMap(final Header[] headers) {
            Map<String, String> headersMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
            for (Header header : headers) {
                if (!skipHeader(header)) {
                    headersMap.put(header.getName(), header.getValue());
                }
            }
            return headersMap;
        }
    
        /**
         * @param header header line to check
         * @return true if the given header should be excluded when signing
         */
        private static boolean skipHeader(final Header header) {
            return ("content-length".equalsIgnoreCase(header.getName())
                    && "0".equals(header.getValue())) // Strip Content-Length: 0
                    || "host".equalsIgnoreCase(header.getName()); // Host comes from endpoint
        }
    
        /**
         * @param mapHeaders Map of header entries
         * @return modeled Header objects
         */
        private static Header[] mapToHeaderArray(final Map<String, String> mapHeaders) {
            Header[] headers = new Header[mapHeaders.size()];
            int i = 0;
            for (Map.Entry<String, String> headerEntry : mapHeaders.entrySet()) {
                headers[i++] = new BasicHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            return headers;
        }
    }
    

    This code can be found here: https://github.com/awsdocs/amazon-opensearch-service-developer-guide/blob/master/sample_code/java/amazon-opensearch-docs-sample-client.zip