From 72210b4fb619870f95f27dd11758852a7b6efe89 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 22 Apr 2016 08:18:28 +0100 Subject: [PATCH] Propagate errors from the initial upload request more appropriately. Fixes issue #456. --- .../Apis/Upload/ResumableUploadTest.cs | 45 +++++++++++++++++++ .../Apis/[Media]/Upload/ResumableUpload.cs | 8 +++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Src/Support/GoogleApis.Tests/Apis/Upload/ResumableUploadTest.cs b/Src/Support/GoogleApis.Tests/Apis/Upload/ResumableUploadTest.cs index c9d110f2bd..1780587a54 100644 --- a/Src/Support/GoogleApis.Tests/Apis/Upload/ResumableUploadTest.cs +++ b/Src/Support/GoogleApis.Tests/Apis/Upload/ResumableUploadTest.cs @@ -33,6 +33,7 @@ namespace Google.Apis.Tests.Apis.Upload { + // TODO: Consider rewriting to use an actual HttpListener like MediaDownloaderTest. [TestFixture] class ResumableUploadTest { @@ -212,6 +213,31 @@ private class SingleChunkMessageHandler : BaseMockMessageHandler } } + private class FailedInitializationMessageHandler : BaseMockMessageHandler + { + private readonly HttpStatusCode status; + private readonly byte[] content; + private readonly string contentType; + + public FailedInitializationMessageHandler(HttpStatusCode status, byte[] content, string contentType) + { + this.status = status; + this.content = content; + this.contentType = contentType; + } + + protected override Task SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) + { + var response = new HttpResponseMessage(); + Assert.That(request.RequestUri.Query, Is.EqualTo("?uploadType=resumable")); + Assert.That(request.Headers.GetValues("X-Upload-Content-Type").First(), + Is.EqualTo("text/plain")); + response.StatusCode = status; + response.Content = new ByteArrayContent(content); + return Task.FromResult(response); + } + } + /// /// A handler which demonstrate a server which reads partial data (e.g. on the first upload request the client /// sends X bytes, but the server actually read only Y of them) @@ -1144,5 +1170,24 @@ public void TestChunkSize() upload.ChunkSize = MockResumableUpload.MinimumChunkSize * 2; } } + + [Test] + public void InitializationRequestFails() + { + string errorText = "Missing foobar"; + var handler = new FailedInitializationMessageHandler( + HttpStatusCode.BadRequest, Encoding.UTF8.GetBytes(errorText), "text/plain; charset=utf-8"); + using (var service = new MockClientService(new BaseClientService.Initializer() + { + HttpClientFactory = new MockHttpClientFactory(handler) + })) + { + var stream = new MemoryStream(Encoding.UTF8.GetBytes(UploadTestData)); + var upload = new MockResumableUpload(service, stream, "text/plain", 100); + var progress = upload.Upload(); + var exception = (GoogleApiException)progress.Exception; + Assert.AreEqual(errorText, exception.Message); + } + } } } \ No newline at end of file diff --git a/Src/Support/GoogleApis/Apis/[Media]/Upload/ResumableUpload.cs b/Src/Support/GoogleApis/Apis/[Media]/Upload/ResumableUpload.cs index d309da88e8..e5e8a2b5f4 100644 --- a/Src/Support/GoogleApis/Apis/[Media]/Upload/ResumableUpload.cs +++ b/Src/Support/GoogleApis/Apis/[Media]/Upload/ResumableUpload.cs @@ -383,6 +383,7 @@ public async Task UploadAsync(CancellationToken cancellationTok { Logger.Error(ex, "MediaUpload - Exception occurred while initializing the upload"); UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived)); + return Progress; } return await UploadCoreAsync(cancellationToken).ConfigureAwait(false); @@ -491,7 +492,12 @@ private async Task InitializeUpload(CancellationToken cancellationToken) { HttpRequestMessage request = CreateInitializeRequest(); var response = await Service.HttpClient.SendAsync(request, cancellationToken).ConfigureAwait(false); - return response.EnsureSuccessStatusCode().Headers.Location; + + if (!response.IsSuccessStatusCode) + { + throw await MediaApiErrorHandling.ExceptionForResponseAsync(Service, response).ConfigureAwait(false); + } + return response.Headers.Location; } ///