// the value of the Task should always be dropped when onSuccess/onFail are provided! internal static async Task <HttpResponse <T> > GetAsync(HttpResponseMessage response, bool ensureSuccess, OnSuccessAsync <T> onSuccess, OnFailAsync <T> onFail) { var genericType = typeof(T); HttpResponse <T> res = null; try { // we need to use await to capture the variable and support finally res = await InternalGetAsync(response, ensureSuccess, onSuccess, onFail, genericType); } finally { // if res == null then either the call threw (and there was no result) or it called onSuccess/onFail // (which return null) so we dispose of the response. // if res is a type that's not stream, it's already buffered, so we dispose of the response. // if res is a stream and it isn't using onSuccess/onFail then we want to give the return value access // to the stream, so we don't want to close the response. if (genericType == typeof(Stream) && res != null) { res._dispose = response; } // if ensureSuccess is true, we want the partial response content to be available to the exception // handler, so don't dispose it in that case else if (!ensureSuccess) { // Content is automatically disposed, see // dotnet/corefx/blob/8c0487bfeff9229beca93dc480028b83d8e39705/src/System.Net.Http/src/System/Net/Http/HttpResponseMessage.cs#L213 response.Dispose(); } } return(res); }
private static async Task <HttpResponse <T> > InternalGetAsync(HttpResponseMessage response, bool ensureSuccess, OnSuccessAsync <T> onSuccess, OnFailAsync <T> onFail, Type genericType) { var res = new HttpResponse <T>(response); var content = response.Content; if (content == null) { throw new UnirestRequestException("HttpResponseMessage.Content was null!"); } if (!res.IsSuccess) { if (onFail != null) { await onFail(new PartialHttpResponse <T>(res, response)); // we return here to avoid misleading exceptions after executing code when onFail is present; since // onFinish must also be present we shouldn't "bubble up" the result to the outside, as that voids // the entire point of using onFail, as it could throw an exception when parsing malformed JSON. // also, this will make GetAsync dispose the response, which is what we want, since we're finished // with it. return(null); } if (ensureSuccess) { throw new UnirestResponseException <T>( $"Request failed with status code {res.Code} ({res.CodeType})", new PartialHttpResponse <T>(res, response)); } } if (genericType == typeof(byte[])) { res.Body = (T)(object)await content.ReadAsByteArrayAsync(); } else if (genericType == typeof(string)) { res.Body = (T)(object)await content.ReadAsStringAsync(); } else if (genericType == typeof(Stream)) { res.Body = (T)(object)await content.ReadAsStreamAsync(); } else { res.Body = JsonConvert.DeserializeObject <T>(await content.ReadAsStringAsync()); } // ReSharper disable once InvertIf if (res.IsSuccess && onSuccess != null) { await onSuccess(res.Body); // return null here since there's no point keeping the response, so we want GetAsync to dispose it return(null); } return(res); }