<PackageReference Include="Relativity.Server.Import.SDK" Version="2.9.2" />

RestClient

class RestClient
Represents a service class object to perform REST operations used by import/export API. This class cannot be inherited.
using Polly; using Relativity.DataExchange.Logger; using Relativity.DataExchange.Resources; using Relativity.Logging; using System; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Net; using System.Net.Http; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Relativity.DataExchange { internal class RestClient { private const HttpStatusCode NoHttpStatusCode = (HttpStatusCode)0; private const int HttpRequestGet = 1; private const int HttpRequestPost = 2; private const int HttpRequestDelete = 3; private readonly RelativityInstanceInfo instance; private readonly ILog logger; public int MaxRetryAttempts { get; set; } public double TimeoutSeconds { get; } public RestClient(RelativityInstanceInfo instance, ILog log, double timeoutSeconds, int maxRetryAttempts) { if (instance == null) throw new ArgumentNullException("instance"); if (log == null) throw new ArgumentNullException("log"); this.instance = instance; logger = log; TimeoutSeconds = timeoutSeconds; MaxRetryAttempts = maxRetryAttempts; } public Task<string> RequestPostStringAsync(string relativeEndpoint, string content, Func<int, TimeSpan> sleepDurationProvider, Action<Exception, TimeSpan, Context> onRetry, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, CancellationToken token) { return RequestAsync(2, relativeEndpoint, content, sleepDurationProvider, onRetry, onEndpointErrorTitle, onEndpointErrorMessage, token); } [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This is done by design for this type of method.")] internal static HttpStatusCode TryGetHttpStatusCode(WebException exception) { try { HttpStatusCode? nullable = (exception.Response as HttpWebResponse)?.StatusCode ?? HttpStatusCode.InternalServerError; return nullable.Value; } catch { return HttpStatusCode.InternalServerError; } } [AsyncStateMachine(typeof(<RequestAsync>d__16))] 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__16 stateMachine = default(<RequestAsync>d__16); 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(<ReadResponseAsync>d__17))] private Task<string> ReadResponseAsync(Uri endpoint, string methodName, HttpResponseMessage response, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage) { <ReadResponseAsync>d__17 stateMachine = default(<ReadResponseAsync>d__17); stateMachine.<>t__builder = AsyncTaskMethodBuilder<string>.Create(); stateMachine.<>4__this = this; stateMachine.endpoint = endpoint; stateMachine.methodName = methodName; stateMachine.response = response; stateMachine.onEndpointErrorTitle = onEndpointErrorTitle; stateMachine.onEndpointErrorMessage = onEndpointErrorMessage; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } private HttpServiceException CreateHttpServiceException(string endpoint, string methodName, HttpStatusCode statusCode, string json, Exception exception, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, bool fatal) { logger.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}", new object[4] { endpoint.Secure(), methodName, statusCode, json }); string text = onEndpointErrorTitle(statusCode); if (string.IsNullOrEmpty(text)) text = Strings.NoEndpointProvided; string text2 = onEndpointErrorMessage(statusCode); if (string.IsNullOrEmpty(text2)) text2 = Strings.NoMessageProvided; string text3 = ExceptionHelper.GetDetailedFatalMessage(statusCode); if (string.IsNullOrEmpty(text3)) text3 = exception.Message; if (string.IsNullOrEmpty(text3)) text3 = Strings.NoMessageProvided; string text4 = string.Format(CultureInfo.CurrentCulture, Strings.HttpExceptionMessage, text, methodName, (int)statusCode, text2, text3); if (statusCode == (HttpStatusCode)0) text4 = string.Format(CultureInfo.CurrentCulture, Strings.HttpNoStatusExceptionMessage, text, methodName, text2, text3); text4 = text4.TrimEnd(Array.Empty<char>()); return new HttpServiceException(text4, exception, statusCode, fatal); } private HttpServiceException CreateHttpServiceException(string endpoint, string methodName, string json, WebException exception, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage, bool fatal) { logger.LogError((Exception)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}", new object[4] { endpoint.Secure(), methodName, exception.Status, json }); string text = onEndpointErrorTitle((HttpStatusCode)0); if (string.IsNullOrEmpty(text)) text = Strings.NoEndpointProvided; string text2 = onEndpointErrorMessage((HttpStatusCode)0); if (string.IsNullOrEmpty(text2)) text2 = Strings.NoMessageProvided; string text3 = ExceptionHelper.GetDetailedFatalMessage(exception.Status); if (string.IsNullOrEmpty(text3)) text3 = exception.Message; if (string.IsNullOrEmpty(text3)) text3 = Strings.NoMessageProvided; string message = string.Format(CultureInfo.CurrentCulture, Strings.WebExceptionMessage, text, methodName, (int)exception.Status, text2, text3).TrimEnd(Array.Empty<char>()); HttpStatusCode statusCode = TryGetHttpStatusCode(exception); return new HttpServiceException(message, exception, statusCode, fatal); } private HttpServiceException CreateTimeoutHttpServiceException(string endpoint, string methodName, Exception exception, Func<HttpStatusCode, string> onEndpointErrorTitle, Func<HttpStatusCode, string> onEndpointErrorMessage) { logger.LogError(exception, "Failed to call the HTTP '{Endpoint}' ({HttpMethod}) endpoint operation because it exceeded the {HttpTimeoutSeconds} second timeout.", new object[3] { endpoint.Secure(), methodName, TimeoutSeconds }); string text = onEndpointErrorTitle(HttpStatusCode.RequestTimeout); if (string.IsNullOrEmpty(text)) text = Strings.NoEndpointProvided; string text2 = onEndpointErrorMessage(HttpStatusCode.RequestTimeout); if (string.IsNullOrEmpty(text2)) text2 = Strings.NoMessageProvided; string text3 = exception.Message; if (string.IsNullOrEmpty(text3)) text3 = Strings.NoMessageProvided; return new HttpServiceException(string.Format(CultureInfo.CurrentCulture, Strings.HttpTimeoutExceptionMessage, text, methodName, TimeoutSeconds, text2, text3).TrimEnd(Array.Empty<char>()), exception, HttpStatusCode.RequestTimeout, false); } private HttpServiceException CreateCredentialNotSupportedException(string endpoint, Func<HttpStatusCode, string> onEndpointErrorTitle) { logger.LogError("Failed to call the HTTP '{Endpoint}' endpoint operation because the supplied Transfer API credential object '{CredentialType}' is not supported.", new object[2] { endpoint.Secure(), instance.Credentials.GetType() }); string text = onEndpointErrorTitle(HttpStatusCode.Unauthorized); if (string.IsNullOrEmpty(text)) text = Strings.NoEndpointProvided; return new HttpServiceException(string.Format(CultureInfo.CurrentCulture, Strings.HttpCredentialNotSupportedExceptionMessage, text, instance.Credentials.GetType().ToString()).TrimEnd(Array.Empty<char>()), HttpStatusCode.Unauthorized, true); } private string GetAuthorizationHeader() { NetworkCredential networkCredential = instance.Credentials as NetworkCredential; if (networkCredential == null) return null; if (networkCredential.UserName == "XxX_BearerTokenCredentials_XxX") return string.Format(CultureInfo.InvariantCulture, "Bearer {0}", networkCredential.Password); string s = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", networkCredential.UserName, networkCredential.Password); return string.Format(CultureInfo.InvariantCulture, "Basic {0}", Convert.ToBase64String(Encoding.ASCII.GetBytes(s))); } } }