aws-cloudformation / aws-cloudformation/cloudformation-cli-java-plugin

AmazonWebServicesClientProxy.logRequestMetadataV2 causes a premature evaluation of the response object

未關閉
#414 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
主要語言
Java
星號
30
分支
48
PR 合併指標
30 天內沒有已合併 PR

描述

**Summary**: `AmazonWebServicesClientProxy.logRequestMetadataV2` causes lazily-evaluated SDK response objects (streams, iterables) to be evaluated immediately. A response resolve would immediately engage the SDK client and execute the service API calls. Whenever a consumer of this response object would access the data again, it would have to be re-resolved and the same API calls would be executed once again. The issue issue exists in the latest lib version.

**Example**: using `injectCredentialsAndInvokeIterableV2` paginated operation causes the SDK to perform 2x more API requests.

**Details**:
`AmazonWebServicesClientProxy` exposes multiple handles to interact with the SDK client. A response object could be either immediately (plain `AwsResponse` object) or lazily (`CompletableFuture`, `SdkIterable`, `ResponseInputStream`) evaluated. A private logging routine called `logRequestMetadataV2` causes lazily evaluated response objects to be evaluated immediately for the sake of logging. The resolve would cause a full range of the service API calls to be executed. By default, the SDK would not perform a deep response cache, hence a secondary access to the response data would once again hook up the SDK client, which would perform the same set of API calls.

```java
public >
IterableT
injectCredentialsAndInvokeIterableV2(final RequestT request, final Function requestFunction) {

AwsRequestOverrideConfiguration overrideConfiguration = AwsRequestOverrideConfiguration.builder()
.credentialsProvider(v2CredentialsProvider).build();

@SuppressWarnings("unchecked")
RequestT wrappedRequest = (RequestT) request.toBuilder().overrideConfiguration(overrideConfiguration).build();

try {
IterableT response = requestFunction.apply(wrappedRequest);
response.forEach(r -> logRequestMetadataV2(request, r)); // <- this invocation would resolve the response object immediately
return response; // <- the response object is returned to the invoker. It would be re-resolved upon a data access.
} catch (final Throwable e) {
loggerProxy.log(String.format("Failed to execute remote function: {%s}", e.getMessage()));
throw e;
}
}
```

**Possible Mitigation**: `logRequestMetadataV2` (and any other kind of non-lazy logging) should be avoided on all non-immediately resolved result types in the following routines:
* `injectCredentialsAndInvokeV2Async`
* `injectCredentialsAndInvokeIterableV2`
* `injectCredentialsAndInvokeV2InputStream`
* `injectCredentialsAndInvokeV2Bytes`

貢獻指南

開啟貢獻指南

研究方向

從 injectCredentialsAndInvokeV2Async、injectCredentialsAndInvokeIterableV2、injectCredentialsAndInvokeV2InputStream 和 injectCredentialsAndInvokeV2Bytes 開始,然後檢查每個方法如何呼叫 logRequestMetadataV2。驗證 lazy 的 CompletableFuture、SdkIterable 和 ResponseInputStream 結果不會在記錄日誌期間被消費,同時確保已立即解析的回應仍會記錄中繼資料,且不會導致重複的服務 API 呼叫。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
java
領域
api, backend
Issue 類型
缺陷
難度
4/5
預估耗時
3-5 天
活躍度
停滯
描述清晰度
基本清楚
新手友好度
42/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。