Created
August 23, 2021 02:47
-
-
Save kofifus/9360bdf9d98925c2e6ab6ccba4fa18ad to your computer and use it in GitHub Desktop.
HttpFile GetToFileAsync, GetToStringAsync, PostToStringAsync
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace System.Net.Http { | |
// holds the non disposable parts of HttpResponseMessage | |
public record HttpResponseInfo(HttpResponseHeaders Headers, bool IsSuccessStatusCode, string? ReasonPhrase, HttpStatusCode HttpStatusCode, HttpResponseHeaders TrailingHeaders, Version Version); | |
// holds Http exception information | |
public record HttpExceptionInfo(string ErrorMessage, WebExceptionStatus? WebExceptionStatus); | |
public record HttpResponse { | |
public HttpResponseInfo? HttpResponseInfo { get; init; } | |
public HttpExceptionInfo? HttpExceptionInfo { get; init; } | |
public HttpResponse(HttpResponseInfo? httpResponseInfo, HttpExceptionInfo? httpExceptionInfo = null) => (HttpResponseInfo, HttpExceptionInfo) = (httpResponseInfo, httpExceptionInfo); | |
public HttpResponse(Exception exception) { | |
HttpResponseInfo = null; | |
if (exception is WebException ex1 && ex1.Status == WebExceptionStatus.ProtocolError) { | |
using HttpWebResponse? httpResponse = (HttpWebResponse?)ex1.Response; | |
HttpExceptionInfo = new(httpResponse?.StatusDescription ?? "", ex1.Status); | |
} | |
else if (exception is WebException ex2) HttpExceptionInfo = new(ex2.FullMessage(), ex2.Status); | |
else if (exception is TaskCanceledException ex3 && ex3.InnerException is TimeoutException) HttpExceptionInfo = new(ex3.InnerException.FullMessage(), WebExceptionStatus.Timeout); | |
else if (exception is TaskCanceledException ex4) HttpExceptionInfo = new(ex4.FullMessage(), WebExceptionStatus.RequestCanceled); | |
else HttpExceptionInfo = new(exception.FullMessage(), null); | |
} | |
public override string ToString() { | |
if (HttpResponseInfo is object && HttpResponseInfo.IsSuccessStatusCode) { | |
var msg = "Success "; | |
msg += $" {Enum.GetName(typeof(HttpStatusCode), HttpResponseInfo.HttpStatusCode)}"; | |
if (HttpResponseInfo.ReasonPhrase is object) msg += $" {HttpResponseInfo.ReasonPhrase}"; | |
return msg; | |
} else { | |
var msg = "Failure"; | |
if (HttpResponseInfo is object) { | |
msg += $" {Enum.GetName(typeof(HttpStatusCode), HttpResponseInfo.HttpStatusCode)}"; | |
if (HttpResponseInfo.ReasonPhrase is object) msg += $" {HttpResponseInfo.ReasonPhrase}"; | |
} | |
if (HttpExceptionInfo is object) { | |
msg += $" {HttpExceptionInfo.ErrorMessage}"; | |
if (HttpExceptionInfo.WebExceptionStatus is object) msg += $" {Enum.GetName(typeof(WebExceptionStatus), HttpExceptionInfo.WebExceptionStatus)}"; | |
} | |
return msg; | |
} | |
} | |
} | |
public static class ExtensionMethods { | |
public static async Task<(bool success, HttpResponse httpResponse)> GetToFileAsync(this HttpClient httpClient, Uri requestUri, string fileToWriteTo, CancellationTokenSource? cts = null, Action<long, int>? progressCallback = null) { | |
var created = false; | |
try { | |
var cancellationToken = cts?.Token ?? default; | |
using HttpResponseMessage responseMsg = await httpClient.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, cancellationToken); | |
var httpResponseInfo = new HttpResponseInfo(responseMsg.Headers, responseMsg.IsSuccessStatusCode, responseMsg.ReasonPhrase, responseMsg.StatusCode, responseMsg.TrailingHeaders, responseMsg.Version); | |
if (!responseMsg.IsSuccessStatusCode) return (false , new(httpResponseInfo)); | |
var contentLength = responseMsg.Content.Headers.ContentLength; | |
using Stream streamToReadFrom = await responseMsg.Content.ReadAsStreamAsync(); | |
using Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create); | |
created = true; | |
var bytesRecieved = (long)-1; | |
var progress = new Progress<long>(totalBytes => { | |
bytesRecieved = totalBytes; | |
if (progressCallback is null) return; | |
var percent = contentLength is object && contentLength != 0 ? (int)Math.Floor(totalBytes / (float)contentLength * 100.0) : -1; | |
progressCallback(totalBytes, percent); | |
}); | |
await streamToReadFrom.CopyToAsync(streamToWriteTo, 81920, progress, cancellationToken); | |
return (true, new(httpResponseInfo)); | |
} | |
catch (Exception ex) { | |
if (created) try { File.Delete(fileToWriteTo); } catch { }; | |
return (false, new(ex)); | |
} | |
} | |
public static async Task<(string? ResponseAsString, HttpResponse httpResponse)> GetToStringAsync(this HttpClient httpClient, Uri requestUri, CancellationTokenSource? cts = null) { | |
try { | |
var cancellationToken = cts?.Token ?? default; | |
using var responseMsg = await httpClient.GetAsync(requestUri, cancellationToken); | |
var httpResponseInfo = new HttpResponseInfo(responseMsg.Headers, responseMsg.IsSuccessStatusCode, responseMsg.ReasonPhrase, responseMsg.StatusCode, responseMsg.TrailingHeaders, responseMsg.Version); | |
if (!responseMsg.IsSuccessStatusCode) return (null, new(httpResponseInfo)); | |
var responseAsString = await responseMsg.Content.ReadAsStringAsync(); | |
return (responseAsString, new(httpResponseInfo)); | |
} | |
catch (Exception ex) { | |
return (null, new(ex)); ; | |
} | |
} | |
public static async Task<(string? ResponseAsString, HttpResponse httpResponse)> PostToStringAsync(this HttpClient httpClient, Uri requestUri, HttpContent postBuffer, CancellationTokenSource? cts = null) { | |
try { | |
var cancellationToken = cts?.Token ?? default; | |
using var responseMsg = await httpClient.PostAsync(requestUri, postBuffer, cancellationToken); | |
var httpResponseInfo = new HttpResponseInfo(responseMsg.Headers, responseMsg.IsSuccessStatusCode, responseMsg.ReasonPhrase, responseMsg.StatusCode, responseMsg.TrailingHeaders, responseMsg.Version); | |
if (!responseMsg.IsSuccessStatusCode) return (null, new(httpResponseInfo)); | |
var responseAsString = await responseMsg.Content.ReadAsStringAsync(); | |
return (responseAsString, new(httpResponseInfo)); | |
} | |
catch (Exception ex) { | |
return (null, new(ex)); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment