// ------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ namespace Microsoft.Graph { using Microsoft.Graph.Core.Models; using Newtonsoft.Json; using System.IO; using System.Net; using System.Net.Http; using System.Threading.Tasks; /// /// The ResponseHandler for upload requests /// internal class UploadResponseHandler { private readonly ISerializer _serializer; /// /// Constructs a new . /// /// public UploadResponseHandler(ISerializer serializer = null) { this._serializer = serializer ?? new Serializer(); } /// /// Process raw HTTP response from Upload request /// /// The type to return /// The HttpResponseMessage to handle. /// public async Task> HandleResponse(HttpResponseMessage response) { if (response.Content == null) { throw new ServiceException(new Error { Code = ErrorConstants.Codes.GeneralException, Message = ErrorConstants.Messages.NoResponseForUpload }); } // Give back the info from the server for ongoing upload as the upload is ongoing using (Stream responseSteam = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) { try { if (!response.IsSuccessStatusCode) { ErrorResponse errorResponse = this._serializer.DeserializeObject(responseSteam); Error error = errorResponse.Error; string rawResponseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false); // Throw exception to know something went wrong. throw new ServiceException(error, response.Headers, response.StatusCode, rawResponseBody); } var uploadResult = new UploadResult(); /* * Check if we have a status code 201 to know if the upload completed successfully. * This will be returned when uploading a FileAttachment with a location header but empty response hence * This could also be returned when uploading a DriveItem with an ItemResponse but no location header. */ if (response.StatusCode == HttpStatusCode.Created) { uploadResult.ItemResponse = this._serializer.DeserializeObject(responseSteam); uploadResult.Location = response.Headers.Location; } else { /* * The response could be either a 200 or a 202 response. * DriveItem Upload returns the upload session in a 202 response while FileAttachment in a 200 response * However, successful upload completion for a DriveItem the response could also come in a 200 response and * hence we validate this by checking the NextExpectedRanges parameter which is present in an ongoing upload */ UploadSession uploadSession = this._serializer.DeserializeObject(responseSteam); if (uploadSession?.NextExpectedRanges != null) { uploadResult.UploadSession = uploadSession; } else { //Upload is most likely done as DriveItem info may come in a 200 response responseSteam.Position = 0; //reset uploadResult.ItemResponse = this._serializer.DeserializeObject(responseSteam); } } return uploadResult; } catch (JsonSerializationException exception) { string rawResponseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false); throw new ServiceException(new Error() { Code = ErrorConstants.Codes.GeneralException, Message = ErrorConstants.Messages.UnableToDeserializexContent, }, response.Headers, response.StatusCode, rawResponseBody, exception); } } } } }