// ------------------------------------------------------------------------------
// 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);
}
}
}
}
}