<PackageReference Include="Relativity.Server.Transfer.SDK" Version="7.7.0" />

RestClient

public class RestClient : IRestClient
using Polly; using Relativity.Transfer.Resources; using System; using System.Globalization; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; namespace Relativity.Transfer { public class RestClient : IRestClient { private const HttpStatusCode NoHttpStatusCode = (HttpStatusCode)0; private const int HttpRequestGet = 1; private const int HttpRequestPost = 2; private const int HttpRequestDelete = 3; private readonly HttpConnectionInfo connectionInfo; private readonly ITransferLog transferLog; public int MaxRetryAttempts { get; set; } public double TimeoutSeconds { get; } public RestClient(HttpConnectionInfo connectionInfo, ITransferLog log) : this(connectionInfo, log, 300, 5) { } public RestClient(HttpConnectionInfo connectionInfo, ITransferLog log, double timeoutSeconds, int maxRetryAttempts) { if (connectionInfo == null) throw new ArgumentNullException("connectionInfo"); if (log == null) throw new ArgumentNullException("log"); this.connectionInfo = connectionInfo; transferLog = log; TimeoutSeconds = timeoutSeconds; MaxRetryAttempts = maxRetryAttempts; } [AsyncStateMachine(typeof(<RequestDeleteAsync>d__15<>))] public Task<T> RequestDeleteAsync<T>(string endpoint, Func<int, TimeSpan> sleepDurationProvider, Action<Exception, TimeSpan, Context> onRetry, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, CancellationToken token) where T : class, new { <RequestDeleteAsync>d__15<T> stateMachine = default(<RequestDeleteAsync>d__15<T>); stateMachine.<>t__builder = AsyncTaskMethodBuilder<T>.Create(); stateMachine.<>4__this = this; stateMachine.endpoint = endpoint; stateMachine.sleepDurationProvider = sleepDurationProvider; stateMachine.onRetry = onRetry; stateMachine.onEndpointErrorTitle = onEndpointErrorTitle; stateMachine.onEndpointErrorMessage = onEndpointErrorMessage; stateMachine.token = token; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(<RequestGetAsync>d__16<>))] public Task<T> RequestGetAsync<T>(string endpoint, Func<int, TimeSpan> sleepDurationProvider, Action<Exception, TimeSpan, Context> onRetry, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, CancellationToken token) where T : class, new { <RequestGetAsync>d__16<T> stateMachine = default(<RequestGetAsync>d__16<T>); stateMachine.<>t__builder = AsyncTaskMethodBuilder<T>.Create(); stateMachine.<>4__this = this; stateMachine.endpoint = endpoint; stateMachine.sleepDurationProvider = sleepDurationProvider; stateMachine.onRetry = onRetry; stateMachine.onEndpointErrorTitle = onEndpointErrorTitle; stateMachine.onEndpointErrorMessage = onEndpointErrorMessage; stateMachine.token = token; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(<RequestPostAsync>d__17<>))] public Task<T> RequestPostAsync<T>(string endpoint, string content, Func<int, TimeSpan> sleepDurationProvider, Action<Exception, TimeSpan, Context> onRetry, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, CancellationToken token) where T : class, new { <RequestPostAsync>d__17<T> stateMachine = default(<RequestPostAsync>d__17<T>); stateMachine.<>t__builder = AsyncTaskMethodBuilder<T>.Create(); stateMachine.<>4__this = this; stateMachine.endpoint = endpoint; stateMachine.content = content; stateMachine.sleepDurationProvider = sleepDurationProvider; stateMachine.onRetry = onRetry; stateMachine.onEndpointErrorTitle = onEndpointErrorTitle; stateMachine.onEndpointErrorMessage = onEndpointErrorMessage; stateMachine.token = token; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public Task<string> RequestJsonPostAsync(string endpoint, string content, Func<int, TimeSpan> sleepDurationProvider, Action<Exception, TimeSpan, Context> onRetry, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, CancellationToken token) { return RequestAsync(2, endpoint, content, sleepDurationProvider, onRetry, onEndpointErrorTitle, onEndpointErrorMessage, token); } [AsyncStateMachine(typeof(<RequestAsync>d__19))] private Task<string> RequestAsync(int method, string endpoint, string content, Func<int, TimeSpan> sleepDurationProvider, Action<Exception, TimeSpan, Context> onRetry, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, CancellationToken token) { <RequestAsync>d__19 stateMachine = default(<RequestAsync>d__19); stateMachine.<>t__builder = AsyncTaskMethodBuilder<string>.Create(); stateMachine.<>4__this = this; stateMachine.method = method; stateMachine.endpoint = endpoint; stateMachine.content = content; stateMachine.sleepDurationProvider = sleepDurationProvider; stateMachine.onRetry = onRetry; stateMachine.onEndpointErrorTitle = onEndpointErrorTitle; stateMachine.onEndpointErrorMessage = onEndpointErrorMessage; stateMachine.token = token; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(<ExecuteCall>d__20))] private Task<string> ExecuteCall(int method, string endpoint, string content, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, CancellationToken token, bool forceTokenRefreshRetry = true) { <ExecuteCall>d__20 stateMachine = default(<ExecuteCall>d__20); stateMachine.<>t__builder = AsyncTaskMethodBuilder<string>.Create(); stateMachine.<>4__this = this; stateMachine.method = method; stateMachine.endpoint = endpoint; stateMachine.content = content; stateMachine.onEndpointErrorTitle = onEndpointErrorTitle; stateMachine.onEndpointErrorMessage = onEndpointErrorMessage; stateMachine.token = token; stateMachine.forceTokenRefreshRetry = forceTokenRefreshRetry; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } private void ConfigureHttpClient(HttpClient client, string endpoint, Func<HttpStatusCode, string> onEndpointErrorTitle) { client.BaseAddress = connectionInfo.Host; client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Add("X-CSRF-Header", string.Empty); string authenticationHeader = connectionInfo.Credential.GetAuthenticationHeader(); if (string.IsNullOrEmpty(authenticationHeader)) throw CreateCredentialNotSupportedTransferException(endpoint, onEndpointErrorTitle, connectionInfo.Credential); client.DefaultRequestHeaders.Add("Authorization", authenticationHeader); if (TimeoutSeconds > 0) client.Timeout = TimeSpan.FromSeconds(TimeoutSeconds); } private static void EnableTls12() { ServicePointManager.SecurityProtocol = (SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12); } private void RefreshCredentials(string methodName) { transferLog.LogInformation("Authorization issue occured. Trying to auto refresh credentials and make next call to {method}", methodName); connectionInfo.Credential.RefreshCredentials(); } private TransferException CreateExtendedTransferException(string endpoint, string methodName, HttpStatusCode statusCode, string json, Exception exception, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, bool fatal) { transferLog.LogError(exception, fatal ? "Fatal attempt to call the HTTP '{Endpoint}' ({HttpMethod}) endpoint operation. HTTP StatusCode={StatusCode}, Response={JsonResponse}" : "Failed to call the HTTP '{Endpoint}' ({HttpMethod}) endpoint operation. HTTP StatusCode={StatusCode}, Response={JsonResponse}", endpoint, methodName, statusCode, json); string text = onEndpointErrorTitle(statusCode); if (string.IsNullOrEmpty(text)) text = CoreStrings.NoEndpointProvided; string text2 = onEndpointErrorMessage(statusCode); if (string.IsNullOrEmpty(text2)) text2 = CoreStrings.NoMessageProvided; string text3 = GlobalSettings.Instance.FatalHttpStatusCodeDetailedMessage(statusCode); if (string.IsNullOrEmpty(text3)) text3 = exception.Message; if (string.IsNullOrEmpty(text3)) text3 = CoreStrings.NoMessageProvided; string text4 = string.Format(CultureInfo.CurrentCulture, CoreStrings.HttpExceptionMessage, text, methodName, (int)statusCode, text2, text3); if (statusCode == (HttpStatusCode)0) text4 = string.Format(CultureInfo.CurrentCulture, CoreStrings.HttpNoStatusExceptionMessage, text, methodName, text2, text3); text4 = text4.TrimEnd(Array.Empty<char>()); return new TransferException(text4, exception, fatal); } private TransferException CreateExtendedTransferException(string endpoint, string methodName, string json, WebException exception, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, bool fatal) { transferLog.LogError(exception, fatal ? "Fatal attempt to call the HTTP '{Endpoint}' ({HttpMethod}) endpoint operation. Web Response Status={WebResponseStatus}, Response={JsonResponse}" : "Failed to call the HTTP '{Endpoint}' ({HttpMethod}) endpoint operation. Web Response Status={WebResponseStatus}, Response={JsonResponse}", endpoint, methodName, exception.Status, json); string text = onEndpointErrorTitle((HttpStatusCode)0); if (string.IsNullOrEmpty(text)) text = CoreStrings.NoEndpointProvided; string text2 = onEndpointErrorMessage((HttpStatusCode)0); if (string.IsNullOrEmpty(text2)) text2 = CoreStrings.NoMessageProvided; string text3 = GlobalSettings.Instance.FatalWebExceptionStatusCodeDetailedMessage(exception.Status); if (string.IsNullOrEmpty(text3)) text3 = exception.Message; if (string.IsNullOrEmpty(text3)) text3 = CoreStrings.NoMessageProvided; return new TransferException(string.Format(CultureInfo.CurrentCulture, CoreStrings.WebExceptionMessage, text, methodName, (int)exception.Status, text2, text3).TrimEnd(Array.Empty<char>()), exception, fatal); } private TransferException CreateTimeoutTransferException(string endpoint, string methodName, Exception exception, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage) { transferLog.LogError(exception, "Failed to call the HTTP '{Endpoint}' ({HttpMethod}) endpoint operation because it exceeded the {HttpTimeoutSeconds} second timeout.", endpoint, methodName, TimeoutSeconds); string text = onEndpointErrorTitle(HttpStatusCode.RequestTimeout); if (string.IsNullOrEmpty(text)) text = CoreStrings.NoEndpointProvided; string text2 = onEndpointErrorMessage(HttpStatusCode.RequestTimeout); if (string.IsNullOrEmpty(text2)) text2 = CoreStrings.NoMessageProvided; string text3 = exception.Message; if (string.IsNullOrEmpty(text3)) text3 = CoreStrings.NoMessageProvided; return new TransferException(string.Format(CultureInfo.CurrentCulture, CoreStrings.HttpTimeoutExceptionMessage, text, methodName, TimeoutSeconds, text2, text3).TrimEnd(Array.Empty<char>()), exception, false); } private TransferException CreateCredentialNotSupportedTransferException(string endpoint, Func<HttpStatusCode, string> onEndpointErrorTitle, IHttpCredential credential) { transferLog.LogError("Failed to call the HTTP '{Endpoint}' endpoint operation because the supplied Transfer API credential object '{CredentialType}' is not supported.", endpoint, credential.GetType()); string text = onEndpointErrorTitle(HttpStatusCode.Unauthorized); if (string.IsNullOrEmpty(text)) text = CoreStrings.NoEndpointProvided; return new TransferException(string.Format(CultureInfo.CurrentCulture, CoreStrings.HttpCredentialNotSupportedExceptionMessage, text, credential.GetType().ToString()).TrimEnd(Array.Empty<char>()), true); } } }