diff --git a/google/cloud/storage/internal/grpc_client.cc b/google/cloud/storage/internal/grpc_client.cc index b313bcfb86a89..f1933be690c8f 100644 --- a/google/cloud/storage/internal/grpc_client.cc +++ b/google/cloud/storage/internal/grpc_client.cc @@ -191,7 +191,7 @@ StatusOr GrpcClient::QueryResumableUpload( response.last_committed_byte = 0; } if (status->has_resource()) { - response.payload = FromProto(status->resource()); + response.payload = FromProto(status->resource(), options()); response.upload_state = ResumableUploadResponse::kDone; } return response; @@ -314,7 +314,9 @@ StatusOr GrpcClient::InsertObjectMedia( auto response = stream->Close(); if (!response) return std::move(response).status(); - if (response->has_resource()) return FromProto(response->resource()); + if (response->has_resource()) { + return FromProto(response->resource(), options()); + } return ObjectMetadata{}; } @@ -714,7 +716,8 @@ StatusOr GrpcClient::ToProto( return result; } -ObjectMetadata GrpcClient::FromProto(google::storage::v2::Object object) { +ObjectMetadata GrpcClient::FromProto(google::storage::v2::Object object, + Options const& options) { auto bucket_id = [](google::storage::v2::Object const& object) { auto const& bucket_name = object.bucket(); auto const pos = bucket_name.find_last_of('/'); @@ -729,6 +732,22 @@ ObjectMetadata GrpcClient::FromProto(google::storage::v2::Object object) { metadata.generation_ = object.generation(); metadata.id_ = metadata.bucket() + "/" + metadata.name() + "/" + std::to_string(metadata.generation()); + auto const metadata_endpoint = [&options]() -> std::string { + if (options.get() != "https://storage.googleapis.com") { + return options.get(); + } + return "https://www.googleapis.com"; + }(); + auto const path = [&options]() -> std::string { + if (!options.has()) return "/storage/v1"; + return "/storage/" + options.get(); + }(); + auto const rel_path = "/b/" + metadata.bucket() + "/o/" + metadata.name(); + metadata.self_link_ = metadata_endpoint + path + rel_path; + metadata.media_link_ = + options.get() + "/download" + path + rel_path + + "?generation=" + std::to_string(metadata.generation()) + "&alt=media"; + metadata.metageneration_ = object.metageneration(); if (object.has_owner()) { metadata.owner_ = FromProto(*object.mutable_owner()); @@ -935,7 +954,7 @@ StatusOr GrpcClient::ToProto( } ResumableUploadResponse GrpcClient::FromProto( - google::storage::v2::WriteObjectResponse const& p) { + google::storage::v2::WriteObjectResponse const& p, Options const& options) { ResumableUploadResponse response; response.upload_state = ResumableUploadResponse::kInProgress; if (p.has_persisted_size() && p.persisted_size() > 0) { @@ -946,7 +965,7 @@ ResumableUploadResponse GrpcClient::FromProto( response.last_committed_byte = 0; } if (p.has_resource()) { - response.payload = FromProto(p.resource()); + response.payload = FromProto(p.resource(), options); response.upload_state = ResumableUploadResponse::kDone; } return response; diff --git a/google/cloud/storage/internal/grpc_client.h b/google/cloud/storage/internal/grpc_client.h index 48a62b8f4364f..0b914f118ecc0 100644 --- a/google/cloud/storage/internal/grpc_client.h +++ b/google/cloud/storage/internal/grpc_client.h @@ -69,6 +69,8 @@ class GrpcClient : public RawClient, std::string const& upload_url); //@} + Options const& options() const { return options_; } + ClientOptions const& client_options() const override; StatusOr ListBuckets( @@ -184,7 +186,8 @@ class GrpcClient : public RawClient, static CustomerEncryption FromProto( google::storage::v2::Object::CustomerEncryption rhs); - static ObjectMetadata FromProto(google::storage::v2::Object object); + static ObjectMetadata FromProto(google::storage::v2::Object object, + Options const& options); static google::storage::v2::ObjectAccessControl ToProto( ObjectAccessControl const& acl); @@ -202,7 +205,8 @@ class GrpcClient : public RawClient, static StatusOr ToProto( InsertObjectMediaRequest const& request); static ResumableUploadResponse FromProto( - google::storage::v2::WriteObjectResponse const&); + google::storage::v2::WriteObjectResponse const& p, + Options const& options); static StatusOr ToProto( ResumableUploadRequest const& request); static google::storage::v2::QueryWriteStatusRequest ToProto( diff --git a/google/cloud/storage/internal/grpc_client_test.cc b/google/cloud/storage/internal/grpc_client_test.cc index d2a882dd6ef1d..ed2dda1d04b4f 100644 --- a/google/cloud/storage/internal/grpc_client_test.cc +++ b/google/cloud/storage/internal/grpc_client_test.cc @@ -133,6 +133,8 @@ TEST(GrpcClientFromProto, ObjectSimple) { "kind": "storage#object", "bucket": "test-bucket", "generation": 2345, + "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/o/test-object-name", + "mediaLink": "https://storage.googleapis.com/download/storage/v1/b/test-bucket/o/test-object-name?generation=2345&alt=media", "owner": { "entity": "test-entity", "entityId": "test-entity-id" @@ -144,7 +146,9 @@ TEST(GrpcClientFromProto, ObjectSimple) { })"""); EXPECT_STATUS_OK(expected); - auto actual = GrpcClient::FromProto(input); + auto actual = GrpcClient::FromProto( + input, + Options{}.set("https://storage.googleapis.com")); EXPECT_EQ(actual, *expected); } diff --git a/google/cloud/storage/internal/grpc_resumable_upload_session.cc b/google/cloud/storage/internal/grpc_resumable_upload_session.cc index 9f450edabea67..32c30fe06d2fc 100644 --- a/google/cloud/storage/internal/grpc_resumable_upload_session.cc +++ b/google/cloud/storage/internal/grpc_resumable_upload_session.cc @@ -141,7 +141,8 @@ StatusOr GrpcResumableUploadSession::UploadGeneric( return last_response_; } done_ = final_chunk; - last_response_ = GrpcClient::FromProto(*std::move(result)); + last_response_ = + GrpcClient::FromProto(*std::move(result), client_->options()); return last_response_; }; diff --git a/google/cloud/storage/object_metadata.cc b/google/cloud/storage/object_metadata.cc index 4c811171bf6fe..37f3d1a8b1534 100644 --- a/google/cloud/storage/object_metadata.cc +++ b/google/cloud/storage/object_metadata.cc @@ -71,7 +71,8 @@ std::ostream& operator<<(std::ostream& os, ObjectMetadata const& rhs) { << rhs.event_based_hold() << ", generation=" << rhs.generation() << ", id=" << rhs.id() << ", kind=" << rhs.kind() << ", kms_key_name=" << rhs.kms_key_name() - << ", md5_hash=" << rhs.md5_hash() << ", media_link=" << rhs.media_link(); + << ", md5_hash=" << rhs.md5_hash() << ", media_link=" << rhs.media_link() + << ", "; if (!rhs.metadata_.empty()) { os << "metadata." << absl::StrJoin(rhs.metadata_, ", metadata.", absl::PairFormatter("=")); diff --git a/google/cloud/storage/tests/object_basic_crud_integration_test.cc b/google/cloud/storage/tests/object_basic_crud_integration_test.cc index 2c636b8c44495..94e78432979e5 100644 --- a/google/cloud/storage/tests/object_basic_crud_integration_test.cc +++ b/google/cloud/storage/tests/object_basic_crud_integration_test.cc @@ -92,12 +92,12 @@ TEST_F(ObjectBasicCRUDIntegrationTest, BasicCRUD) { EXPECT_EQ(get_meta->kind(), insert_meta->kind()); EXPECT_EQ(get_meta->kms_key_name(), insert_meta->kms_key_name()); EXPECT_EQ(get_meta->md5_hash(), insert_meta->md5_hash()); - // EXPECT_EQ(get_meta->media_link(), insert_meta->media_link()); + EXPECT_EQ(get_meta->media_link(), insert_meta->media_link()); EXPECT_EQ(get_meta->metageneration(), insert_meta->metageneration()); // EXPECT_EQ(get_meta->owner(), insert_meta->owner()); EXPECT_EQ(get_meta->retention_expiration_time(), insert_meta->retention_expiration_time()); - // EXPECT_EQ(get_meta->self_link(), insert_meta->self_link()); + EXPECT_EQ(get_meta->self_link(), insert_meta->self_link()); EXPECT_EQ(get_meta->size(), insert_meta->size()); EXPECT_EQ(get_meta->storage_class(), insert_meta->storage_class()); EXPECT_EQ(get_meta->temporary_hold(), insert_meta->temporary_hold());