如何将 AWSRequestSigningApacheInterceptor 与 AWS SDK2 结合使用 [英] How to use AWSRequestSigningApacheInterceptor with AWS SDK2
问题描述
我正在尝试在已经使用 Apache HTTP 客户端的现有 Java 代码上使用对 Neptune SPARQL 的 REST 调用.我不想混合搭配 AWS SDK1 和 SDK2(我用于将 owl 加载到 Neptune 的 S3 部分).
I am trying to use REST calls to Neptune SPARQL on existing Java code which already uses Apache HTTP clients. I'd like to not mix and match AWS SDK1 and SDK2 (which I use for the S3 portion of loading owl to Neptune).
我看到了这些解决方案:
I see these solutions:
AWSRequestSigningApacheInterceptor 适用于 SDK1,但在 SDK2 中找不到等效项.
AWSRequestSigningApacheInterceptor that works with SDK1, but can't find the equivalent in SDK2.
aws-request-signing-apache-github 上的拦截器 用于构建适配器类,以便它可以在 SDK 2 中与混合匹配 SDK 1 & 一起使用.2
aws-request-signing-apache-interceptor on github for building an adaptor class so it can be used in SDK 2 with mix-and-match SDK 1 & 2
javaquery/Examples 其中 Vicky Thakor 变得更加通用并且刚刚实现了 V4签署任何 Java REST 实现
javaquery/Examples where Vicky Thakor has gone even more generic and just implemented the V4 signing for any Java REST implementation
但这些都不是我所期望的:AWS SDK 2 的 Apache 拦截器的 AWS 或 Apache 实现.
But none of these is what I expected: an AWS or Apache implmentation of an Apache Interceptor for AWS SDK 2.
有这种事吗?或者上述解决方案之一是目前最好的解决方案吗?
Is there such a thing? or is one of the above solutions the best available at the moment?
推荐答案
这里有一些最少的代码,用于向 ElasticSearch API(不是 Neptune SPARQL,但都是 REST)发出一些不同的经过身份验证的 REST 请求.
Here is some minimal code to make a few different authenticated REST requests to the ElasticSearch API (not Neptune SPARQL, but it's all REST).
pom.xml:
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<!-- version number is not needed due to the BOM below -->
</dependency>
<!-- below is needed for this issue: https://github.com/aws/aws-sdk-java-v2/issues/652 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.11</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
<!-- version number is not needed due to the BOM below -->
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.7.36</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
这是Java:
import org.json.JSONObject;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.auth.signer.Aws4Signer;
import software.amazon.awssdk.auth.signer.params.Aws4SignerParams;
import software.amazon.awssdk.http.*;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.utils.StringInputStream;
import java.io.*;
public class ElasticSearch implements Closeable {
private static final String HOST = "my-elasticsearch-3490jvoi2je3o.us-east-2.es.amazonaws.com";
private Aws4SignerParams params = Aws4SignerParams.builder()
.awsCredentials(DefaultCredentialsProvider.create().resolveCredentials())
.signingName("es") // "es" stands for elastic search. Change this to match your service!
.signingRegion(Region.US_EAST_2)
.build();
private Aws4Signer signer = Aws4Signer.create();
SdkHttpClient httpClient = ApacheHttpClient.builder().build();
/** @param path should not have a leading "/" */
private HttpExecuteResponse restRequest(SdkHttpMethod method, String path) throws IOException {
return restRequest(method, path, null);
}
private HttpExecuteResponse restRequest(SdkHttpMethod method, String path, JSONObject body)
throws IOException {
SdkHttpFullRequest.Builder b = SdkHttpFullRequest.builder()
.encodedPath(path)
.host(HOST)
.method(method)
.protocol("https");
if (body != null) {
b.putHeader("Content-Type", "application/json; charset=utf-8");
b.contentStreamProvider(() -> new StringInputStream(body.toString()));
}
SdkHttpFullRequest request = b.build();
// now sign it
SdkHttpFullRequest signedRequest = signer.sign(request, params);
HttpExecuteRequest.Builder rb = HttpExecuteRequest.builder().request(signedRequest);
// !!!: line below is necessary even though the contentStreamProvider is in the request.
// Otherwise the body will be missing from the request and auth signature will fail.
request.contentStreamProvider().ifPresent(c -> rb.contentStreamProvider(c));
return httpClient.prepareRequest(rb.build()).call();
}
public void search(String indexName, String searchString) throws IOException {
HttpExecuteResponse result = restRequest(SdkHttpMethod.GET, indexName+"/_search",
new JSONObject().put("query",
new JSONObject().put("match",
new JSONObject().put("txt",
new JSONObject().put("query", searchString)))));
System.out.println("Search results:");
System.out.println(new JSONObject(result.responseBody()));
}
/** @return success status */
public boolean createIndex(String indexName) throws IOException {
if (indexName.contains("/")) {
throw new RuntimeException("indexName cannot contain '/' character");
}
HttpExecuteResponse r = restRequest(SdkHttpMethod.PUT, indexName);
System.out.println("PUT /"+indexName + " response code: " + r.httpResponse().statusCode());
printInputStream(r.responseBody().get());
return r.httpResponse().isSuccessful();
}
private void printInputStream(InputStream is) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
String readLine;
while (((readLine = br.readLine()) != null)) System.out.println(readLine);
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean postDoc(String indexName, String docId, JSONObject docBody) throws IOException {
HttpExecuteResponse response = restRequest(
SdkHttpMethod.PUT,
String.format("%s/_doc/%s", indexName, docId),
docBody
);
System.out.println("Index operation response:");
printInputStream(response.responseBody().get());
return response.httpResponse().isSuccessful();
}
@Override
public void close() throws IOException {
httpClient.close();
}
}
这篇关于如何将 AWSRequestSigningApacheInterceptor 与 AWS SDK2 结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!