@@ -160,102 +160,6 @@ Status CurlClient::SetupBuilder(CurlRequestBuilder& builder,
160160 return Status ();
161161}
162162
163- template <typename RequestType>
164- StatusOr<std::unique_ptr<ResumableUploadSession>>
165- CurlClient::CreateResumableSessionGeneric (RequestType const & request) {
166- auto session_id =
167- request.template GetOption <UseResumableUploadSession>().value_or (" " );
168- if (!session_id.empty ()) {
169- return RestoreResumableSession (session_id);
170- }
171-
172- CurlRequestBuilder builder (
173- upload_endpoint_ + " /b/" + request.bucket_name () + " /o" , upload_factory_);
174- auto status = SetupBuilderCommon (builder, " POST" );
175- if (!status.ok ()) {
176- return status;
177- }
178-
179- // In most cases we use `SetupBuilder()` to setup all these options in the
180- // request. But in this case we cannot because that might also set
181- // `Content-Type` to the wrong value. Instead we have to explicitly list all
182- // the options here. Somebody could write a clever meta-function to say
183- // "set all the options except `ContentType`, but I think that is going to be
184- // very hard to understand.
185- builder.AddOption (request.template GetOption <EncryptionKey>());
186- builder.AddOption (request.template GetOption <IfGenerationMatch>());
187- builder.AddOption (request.template GetOption <IfGenerationNotMatch>());
188- builder.AddOption (request.template GetOption <IfMetagenerationMatch>());
189- builder.AddOption (request.template GetOption <IfMetagenerationNotMatch>());
190- builder.AddOption (request.template GetOption <KmsKeyName>());
191- builder.AddOption (request.template GetOption <PredefinedAcl>());
192- builder.AddOption (request.template GetOption <Projection>());
193- builder.AddOption (request.template GetOption <UserProject>());
194- builder.AddOption (request.template GetOption <CustomHeader>());
195- builder.AddOption (request.template GetOption <Fields>());
196- builder.AddOption (request.template GetOption <IfMatchEtag>());
197- builder.AddOption (request.template GetOption <IfNoneMatchEtag>());
198- builder.AddOption (request.template GetOption <QuotaUser>());
199- builder.AddOption (request.template GetOption <UploadContentLength>());
200- SetupBuilderUserIp (builder, request);
201-
202- builder.AddQueryParameter (" uploadType" , " resumable" );
203- builder.AddHeader (" Content-Type: application/json; charset=UTF-8" );
204- nlohmann::json resource;
205- if (request.template HasOption <WithObjectMetadata>()) {
206- resource = ObjectMetadataJsonForInsert (
207- request.template GetOption <WithObjectMetadata>().value ());
208- }
209- if (request.template HasOption <ContentEncoding>()) {
210- resource[" contentEncoding" ] =
211- request.template GetOption <ContentEncoding>().value ();
212- }
213- if (request.template HasOption <ContentType>()) {
214- resource[" contentType" ] = request.template GetOption <ContentType>().value ();
215- }
216- if (request.template HasOption <Crc32cChecksumValue>()) {
217- resource[" crc32c" ] =
218- request.template GetOption <Crc32cChecksumValue>().value ();
219- }
220- if (request.template HasOption <MD5HashValue>()) {
221- resource[" md5Hash" ] = request.template GetOption <MD5HashValue>().value ();
222- }
223-
224- if (resource.empty ()) {
225- builder.AddQueryParameter (" name" , request.object_name ());
226- } else {
227- resource[" name" ] = request.object_name ();
228- }
229-
230- std::string request_payload;
231- if (!resource.empty ()) {
232- request_payload = resource.dump ();
233- }
234- builder.AddHeader (" Content-Length: " +
235- std::to_string (request_payload.size ()));
236- auto http_response = builder.BuildRequest ().MakeRequest (request_payload);
237- if (!http_response.ok ()) {
238- return std::move (http_response).status ();
239- }
240- if (http_response->status_code >= HttpStatusCode::kMinNotSuccess ) {
241- return AsStatus (*http_response);
242- }
243- auto response =
244- ResumableUploadResponse::FromHttpResponse (*std::move (http_response));
245- if (!response.ok ()) {
246- return std::move (response).status ();
247- }
248- if (response->upload_session_url .empty ()) {
249- std::ostringstream os;
250- os << __func__ << " - invalid server response, parsed to " << *response;
251- return Status (StatusCode::kInternal , std::move (os).str ());
252- }
253- return std::unique_ptr<ResumableUploadSession>(
254- absl::make_unique<CurlResumableUploadSession>(
255- shared_from_this (), std::move (response->upload_session_url ),
256- std::move (request.template GetOption <CustomHeader>())));
257- }
258-
259163CurlClient::CurlClient (google::cloud::Options options)
260164 : opts_(std::move(options)),
261165 backwards_compatibility_options_ (
@@ -718,7 +622,91 @@ StatusOr<RewriteObjectResponse> CurlClient::RewriteObject(
718622
719623StatusOr<std::unique_ptr<ResumableUploadSession>>
720624CurlClient::CreateResumableSession (ResumableUploadRequest const & request) {
721- return CreateResumableSessionGeneric (request);
625+ auto session_id = request.GetOption <UseResumableUploadSession>().value_or (" " );
626+ if (!session_id.empty ()) {
627+ return RestoreResumableSession (session_id);
628+ }
629+
630+ CurlRequestBuilder builder (
631+ upload_endpoint_ + " /b/" + request.bucket_name () + " /o" , upload_factory_);
632+ auto status = SetupBuilderCommon (builder, " POST" );
633+ if (!status.ok ()) {
634+ return status;
635+ }
636+
637+ // In most cases we use `SetupBuilder()` to set up all these options in the
638+ // request. But in this case we cannot because that might also set
639+ // `Content-Type` to the wrong value. Instead, we have to explicitly list all
640+ // the options here. Somebody could write a clever meta-function to say
641+ // "set all the options except `ContentType`, but I think that is going to be
642+ // very hard to understand.
643+ builder.AddOption (request.GetOption <EncryptionKey>());
644+ builder.AddOption (request.GetOption <IfGenerationMatch>());
645+ builder.AddOption (request.GetOption <IfGenerationNotMatch>());
646+ builder.AddOption (request.GetOption <IfMetagenerationMatch>());
647+ builder.AddOption (request.GetOption <IfMetagenerationNotMatch>());
648+ builder.AddOption (request.GetOption <KmsKeyName>());
649+ builder.AddOption (request.GetOption <PredefinedAcl>());
650+ builder.AddOption (request.GetOption <Projection>());
651+ builder.AddOption (request.GetOption <UserProject>());
652+ builder.AddOption (request.GetOption <CustomHeader>());
653+ builder.AddOption (request.GetOption <Fields>());
654+ builder.AddOption (request.GetOption <IfMatchEtag>());
655+ builder.AddOption (request.GetOption <IfNoneMatchEtag>());
656+ builder.AddOption (request.GetOption <QuotaUser>());
657+ builder.AddOption (request.GetOption <UploadContentLength>());
658+ SetupBuilderUserIp (builder, request);
659+
660+ builder.AddQueryParameter (" uploadType" , " resumable" );
661+ builder.AddHeader (" Content-Type: application/json; charset=UTF-8" );
662+ nlohmann::json resource;
663+ if (request.HasOption <WithObjectMetadata>()) {
664+ resource = ObjectMetadataJsonForInsert (
665+ request.GetOption <WithObjectMetadata>().value ());
666+ }
667+ if (request.HasOption <ContentEncoding>()) {
668+ resource[" contentEncoding" ] = request.GetOption <ContentEncoding>().value ();
669+ }
670+ if (request.HasOption <ContentType>()) {
671+ resource[" contentType" ] = request.GetOption <ContentType>().value ();
672+ }
673+ if (request.HasOption <Crc32cChecksumValue>()) {
674+ resource[" crc32c" ] = request.GetOption <Crc32cChecksumValue>().value ();
675+ }
676+ if (request.HasOption <MD5HashValue>()) {
677+ resource[" md5Hash" ] = request.GetOption <MD5HashValue>().value ();
678+ }
679+
680+ if (resource.empty ()) {
681+ builder.AddQueryParameter (" name" , request.object_name ());
682+ } else {
683+ resource[" name" ] = request.object_name ();
684+ }
685+
686+ std::string request_payload;
687+ if (!resource.empty ()) request_payload = resource.dump ();
688+
689+ builder.AddHeader (" Content-Length: " +
690+ std::to_string (request_payload.size ()));
691+ auto http_response = builder.BuildRequest ().MakeRequest (request_payload);
692+ if (!http_response.ok ()) {
693+ return std::move (http_response).status ();
694+ }
695+ if (http_response->status_code >= HttpStatusCode::kMinNotSuccess ) {
696+ return AsStatus (*http_response);
697+ }
698+ auto response =
699+ ResumableUploadResponse::FromHttpResponse (*std::move (http_response));
700+ if (!response.ok ()) return std::move (response).status ();
701+ if (response->upload_session_url .empty ()) {
702+ std::ostringstream os;
703+ os << __func__ << " - invalid server response, parsed to " << *response;
704+ return Status (StatusCode::kInternal , std::move (os).str ());
705+ }
706+ return std::unique_ptr<ResumableUploadSession>(
707+ absl::make_unique<CurlResumableUploadSession>(
708+ shared_from_this (), std::move (response->upload_session_url ),
709+ request.GetOption <CustomHeader>()));
722710}
723711
724712StatusOr<std::unique_ptr<ResumableUploadSession>>
0 commit comments