userver: S3 client tutorial
Loading...
Searching...
No Matches
S3 client tutorial

Before you start

Take a look at official S3 documentation. Have your access key and secret key ready.

Step by step guide

In this example, we will create a client and make a request to S3 endpoint.

Installation

Find and link to userver module:

# cmake
find_package(userver COMPONENTS core s3api REQUIRED)
add_library(${PROJECT_NAME}_objs OBJECT
src/s3api_client.cpp
)
target_link_libraries(${PROJECT_NAME}_objs PUBLIC userver::s3api)
target_include_directories(${PROJECT_NAME}_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)

Creating client in code

We recomend wrapping your clients into some component. This way you can make sure that reference to http_client outlives S3 client. It can look, for example, like this:

// This component is not required to create S3 api client. It is used for demonstation
// purposes only.
class S3ApiSampleComponent : public components::LoggableComponentBase {
public:
// `kName` is used as the component name in static config
static constexpr std::string_view kName = "s3-sample-component";
S3ApiSampleComponent(const components::ComponentConfig& config, const components::ComponentContext& context);
s3api::ClientPtr GetClient();
private:
// http_client MUST outlive any dependent s3 client
clients::http::Client& http_client_;
};

To create client itself, you do only few simple steps:

s3api::ClientPtr S3ApiSampleComponent::GetClient() {
// Create connection settings
auto connection_cfg = s3api::ConnectionCfg(
std::chrono::milliseconds{100}, /* timeout */
2, /* retries */
std::nullopt /* proxy */
);
// Create connection object
auto s3_connection = s3api::MakeS3Connection(
http_client_, s3api::S3ConnectionType::kHttps, "s3-some-site.awsornot.com", connection_cfg
);
// Create authorizer.
auto auth = std::make_shared<s3api::authenticators::AccessKey>("my-access-key", s3api::Secret("my-secret-key"));
// create and return client
return s3api::GetS3Client(s3_connection, auth, "mybucket");
}

Using client

Here is usage example

void DoVeryImportantThingsInS3(s3api::ClientPtr client) {
std::string path = "path/to/object";
std::string data{"some string data"};
client->PutObject(path, data);
client->GetObject(path);
}

Testing

We provide google mock for client, that you can access by including header

#include <userver/s3api/utest/client_gmock.hpp>

With this mock, you have full power of Google Mock at your fingertips:

UTEST(S3ClientTest, HappyPath) {
auto mock = std::make_shared<s3api::GMockClient>();
EXPECT_CALL(
*mock,
PutObject(
std::string_view{"path/to/object"}, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_
)
)
.Times(1)
.WillOnce(::testing::Return("OK"));
EXPECT_CALL(*mock, GetObject(std::string_view{"path/to/object"}, ::testing::_, ::testing::_, ::testing::_))
.Times(1)
.WillOnce(::testing::Return(std::string{"some data"}));
samples::DoVeryImportantThingsInS3(mock);
}

To add tests to your project, add appropriate lines to CMakeLists.txt, like this:

# cmake
add_executable(${PROJECT_NAME}-unittest unittests/client_test.cpp)
target_link_libraries(${PROJECT_NAME}-unittest
${PROJECT_NAME}_objs
userver::utest
userver::s3api-utest
)
add_google_tests(${PROJECT_NAME}-unittest)

Testsuite support

Testsuite module is provided as part of testsuite plugins and can be found at:

testsuite/pytest_plugins/pytest_userver/plugins/s3api.py

Full Sources

See the full example at: