AWS SDK for C++を利用した開発でMinioを利用する際にハマったのでメモ。
AWS SDK for C++とMinioについては下記をご参考ください。
C++初心者がMacでAWS SDK for C++を利用してAmazon DynamoDBにアクセスする - Qiita
https://qiita.com/kai_kou/items/fe9e3525d2023dc955a5
C++初心者がDockerで開発環境をつくってみた - Qiita
https://qiita.com/kai_kou/items/1f4b9a45a5d4d6788649
S3互換のオブジェクトストレージ MinioをDocker Composeで利用する - Qiita
https://qiita.com/kai_kou/items/9fe06d4d24928d9efa2a
実装
AWS SDK for C++のバージョンは1.6.0となります。(2019/02/18時点)
aws/aws-sdk-cpp: AWS SDK for C++
https://github.com/aws/aws-sdk-cpp
下記のサンプルのエンドポイントをMinioに変更して動作するようにします。
C++ Code Samples for Amazon S3 - AWS Code Sample
https://docs.aws.amazon.com/ja_jp/code-samples/latest/catalog/code-catalog-cpp-example_code-s3.html
put_object.cpp - AWS Code Sample
https://docs.aws.amazon.com/ja_jp/code-samples/latest/catalog/cpp-s3-put_object.cpp.html
/*
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is 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/
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.
*/
#include <aws/core/Aws.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/PutObjectRequest.h>
#include <iostream>
#include <fstream>
/**
* Put an object from an Amazon S3 bucket.
*/
int main(int argc, char** argv)
{
if (argc < 4)
{
std::cout << std::endl <<
"To run this example, supply the name of an S3 bucket, destination key, and file to upload."
<< std::endl << std::endl <<
"Ex: put_object <bucketname> <keyname> <filename> <optional:region>" << std::endl;
exit(1);
}
Aws::SDKOptions options;
Aws::InitAPI(options);
{
const Aws::String bucket_name = argv[1];
const Aws::String key_name = argv[2];
const Aws::String file_name = argv[3];
const Aws::String region(argc > 4 ? argv[4] : "");
std::cout << "Uploading " << file_name << " to S3 bucket " <<
bucket_name << " at key " << key_name << std::endl;
Aws::Client::ClientConfiguration clientConfig;
if (!region.empty())
clientConfig.region = region;
Aws::S3::S3Client s3_client(clientConfig);
Aws::S3::Model::PutObjectRequest object_request;
object_request.WithBucket(bucket_name).WithKey(key_name);
// Binary files must also have the std::ios_base::bin flag or'ed in
auto input_data = Aws::MakeShared<Aws::FStream>("PutObjectInputStream",
file_name.c_str(), std::ios_base::in | std::ios_base::binary);
object_request.SetBody(input_data);
auto put_object_outcome = s3_client.PutObject(object_request);
if (put_object_outcome.IsSuccess())
{
std::cout << "Done!" << std::endl;
}
else
{
std::cout << "PutObject error: " <<
put_object_outcome.GetError().GetExceptionName() << " " <<
put_object_outcome.GetError().GetMessage() << std::endl;
}
}
Aws::ShutdownAPI(options);
}
上記サンプルで、Minioへアクセスするようにエンドポイントを指定してやればよいわけですが、いろいろとハマったのでポイントです。
エンドポイントの指定はendpointOverride
とscheme
を利用する
Aws::Client::ClientConfiguration
にあるendpointOverride
でエンドポイントが指定できます。HTTPアクセスの場合、scheme
の指定も必要です。
AWS SDK for C++: Aws::Client::ClientConfiguration Struct Reference
https://sdk.amazonaws.com/cpp/api/LATEST/struct_aws_1_1_client_1_1_client_configuration.html
Aws::Client::ClientConfiguration clientConfig;
if (!region.empty())
clientConfig.region = region;
clientConfig.scheme = Aws::Http::Scheme::HTTP;
clientConfig.endpointOverride = endpoint;
公式のドキュメントをみるとauthenticationRegion
の指定も必要とありますが、最新バージョン1.6.0
(2019/02/18時点)では定義されていませんので気をつけましょう。
古いドキュメント
AWS Client Configuration - AWS SDK for C++
https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/client-config.html
古いドキュメント
AWS SDK for C++: Aws::Client::ClientConfiguration Struct Reference
https://sdk.amazonaws.com/cpp/api/0.12.9/df/d19/struct_aws_1_1_client_1_1_client_configuration.html
S3Client
作成時にuseVirtualAdressing
を無効にする
Minioのエンドポイントがlocalhost:9000
となり、useVirtualAdressing
が有効の場合、アクセスすることができません。
useVirtualAdressing
を指定するコンストラクタではCredentials
などを渡す必要があるため、Aws::Auth::EnvironmentAWSCredentialsProvider().GetAWSCredentials()
を利用します。アクセスキーとシークレットをパラメータにCredentials
を作成してもOKです。
AWS SDK for C++: Aws::S3::S3Client Class Reference
https://sdk.amazonaws.com/cpp/api/LATEST/class_aws_1_1_s3_1_1_s3_client.html#ac8168b12d0e630dcdc5cd912d38d8787
VirtualAdressing
(仮想ホスト形式)については下記が参考になります。
S3のバケットURL(仮想ホスト形式とパス形式) - Qiita
https://qiita.com/ryo0301/items/48120379b240ab071028
AWS CLIのS3接続先の選択動作とaddressing_styleオプション - おぎろぐはてブロ
https://iogi.hatenablog.com/entry/s3-addressing-style
#include <aws/core/auth/AWSCredentialsProvider.h>
#include <aws/core/auth/AWSAuthSigner.h>
(略)
// 環境変数などから認証情報を取得する
Aws::Auth::AWSCredentials cred = Aws::Auth::EnvironmentAWSCredentialsProvider().GetAWSCredentials();
// useVirtualAdressingをfalseにする
Aws::S3::S3Client s3_client(cred, clientConfig, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, false);
こちらも過去バージョンだとS3Clientコストラクタのパラメータが一部異なるので注意しましょう。
古いドキュメント
AWS SDK for C++: Aws::S3::S3Client Class Reference
https://sdk.amazonaws.com/cpp/api/0.12.9/d7/db7/class_aws_1_1_s3_1_1_s3_client.html
まとめ
AWS SDK for C++のバージョンによって仕様が異なり、ネットで検索して得られる情報では解決できない可能性がありますので、最終的には実装や最新のドキュメントを確認するようにしましょう。
参考
C++初心者がMacでAWS SDK for C++を利用してAmazon DynamoDBにアクセスする - Qiita
https://qiita.com/kai_kou/items/fe9e3525d2023dc955a5
C++初心者がDockerで開発環境をつくってみた - Qiita
https://qiita.com/kai_kou/items/1f4b9a45a5d4d6788649
aws/aws-sdk-cpp: AWS SDK for C++
https://github.com/aws/aws-sdk-cpp
C++ Code Samples for Amazon S3 - AWS Code Sample
https://docs.aws.amazon.com/ja_jp/code-samples/latest/catalog/code-catalog-cpp-example_code-s3.html
put_object.cpp - AWS Code Sample
https://docs.aws.amazon.com/ja_jp/code-samples/latest/catalog/cpp-s3-put_object.cpp.html
AWS SDK for C++: Aws::Client::ClientConfiguration Struct Reference
https://sdk.amazonaws.com/cpp/api/LATEST/struct_aws_1_1_client_1_1_client_configuration.html
AWS SDK for C++: Aws::S3::S3Client Class Reference
https://sdk.amazonaws.com/cpp/api/LATEST/class_aws_1_1_s3_1_1_s3_client.html#ac8168b12d0e630dcdc5cd912d38d8787
S3のバケットURL(仮想ホスト形式とパス形式) - Qiita
https://qiita.com/ryo0301/items/48120379b240ab071028
AWS CLIのS3接続先の選択動作とaddressing_styleオプション - おぎろぐはてブロ
https://iogi.hatenablog.com/entry/s3-addressing-style
S3互換のオブジェクトストレージ MinioをDocker Composeで利用する - Qiita
https://qiita.com/kai_kou/items/9fe06d4d24928d9efa2a