AWS C++ SDK GetParametersRequest响应非空但返回空结果列表问题
问题现象
调用GetParametersRequest接口从AWS Parameter Store拉取参数时,接口返回成功状态,在SetDataReceivedEvent回调中可以正常读到完整的JSON格式有效响应,本地AWS区域、访问凭证配置均正常,但最终返回的结果对象中参数列表长度始终为0,复现代码如下:
#include <aws/ssm/SSMClient.h> #include <aws/core/auth/AWSCredentials.h> #include <aws/ssm/model/GetParametersByPathRequest.h> #include <aws/ssm/model/GetParametersByPathResult.h> #include <aws/ssm/model/GetParametersRequest.h> #include <aws/ssm/model/GetParametersResult.h> void getParam(const Aws::SSM::SSMClient& client) { Aws::SSM::Model::GetParametersRequest request; request.SetNames({ "/some/config/parameter" }); request.SetWithDecryption(true); request.SetWithDecryption(true); request.SetDataSentEventHandler([&request](const Aws::Http::HttpRequest*, long long) { std::cout << "Request sent:\n" << request.SerializePayload() << std::endl; }); request.SetDataReceivedEventHandler([](const Aws::Http::HttpRequest*, Aws::Http::HttpResponse* resp, long long) { std::cout << "\nResponse body:\n" << resp->GetResponseBody().rdbuf() << std::endl; }); Aws::SSM::Model::GetParametersOutcome result = client.GetParameters(request); if (!result.IsSuccess()) { std::cout << "failed : " << result.GetError() << std::endl; } else { std::cout << "succeed" << std::endl; auto response = result.GetResult(); auto params = response.GetParameters(); std::cout << "size : " << params.size() << std::endl; for (const auto& r : params) { std::cout << "name : " << r.GetName() << " value : " << r.GetValue() << std::endl; } } } int main() { Aws::SDKOptions options; options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace; Aws::InitAPI(options); { Aws::Client::ClientConfiguration configs; if (configs.region.empty()) { configs.region = "US_EAST_1"; } Aws::SSM::SSMClient client(configs); getParam(client); } Aws::ShutdownAPI(options); return 0; }
故障原因
核心问题出在自定义的DataReceivedEventHandler回调逻辑:回调中调用resp->GetResponseBody().rdbuf()输出响应内容时,会将响应体IO流的读取指针移动到流末尾。回调执行结束后,AWS C++ SDK会从同一个响应体流读取内容做反序列化,填充GetParametersResult对象,此时流已经处于EOF状态,读不到任何有效内容,最终反序列化得到的参数列表长度为0,和接口权限、凭证配置无关。
另外代码中区域配置的字符串格式存在错误:正确的AWS区域标识为全小写加短横线格式,即us-east-1,写成US_EAST_1会导致SDK无法正确识别区域配置。
修复方法
不需要手动解析响应体,两种修复方式可选:
- 移除自定义的
SetDataReceivedEventHandler回调,SDK会自动完成响应流读取和结果反序列化,直接从结果对象即可拿到参数列表。 - 如果需要在回调中打印/查看响应体内容,读取完流内容后,必须将流的读取指针重置回流的起始位置,保证后续SDK反序列化逻辑可以正常读取全部内容,修正后的回调代码如下:
request.SetDataReceivedEventHandler([](const Aws::Http::HttpRequest*, Aws::Http::HttpResponse* resp, long long) { // 读取并打印响应体 std::cout << "\nResponse body:\n" << resp->GetResponseBody().rdbuf() << std::endl; // 重置流读取指针到起始位置,供SDK后续反序列化使用 resp->GetResponseBody().seekg(0); });
内容的提问来源于stack exchange,提问作者Mher Didaryan
相关产品推荐
相关产品推荐

