using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace Helpers { public class RestApiResponse<T> { public RestApiResponse(string url, HttpResponseMessage response, TimeSpan duration, string content, T result) { Url = url; Response = response; Duration = duration; Content = content; Result = result; } public readonly string Url; public readonly HttpResponseMessage Response; public readonly TimeSpan Duration; public HttpStatusCode Status => Response.StatusCode; public bool Success => Response.IsSuccessStatusCode; public readonly string Content; public readonly T Result; } public class RequestSettings { public RequestSettings() { } public RequestSettings(HttpMethod method, object content = null, string contentType = "application/json") { Method = method; Content = content; ContentType = contentType; } public HttpMethod Method { get; set; } = HttpMethod.Get; public object Content { get; set; } = null; public string ContentType { get; set; } = "application/json"; public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>(); public bool ThrowOnErrorStatus { get; set; } = false; } public class RestApiClient { private const string AuthorizationHeader = "Authorization"; public string BearerToken { get; set; } private static readonly HttpClientHandler _httpClientHandler = new HttpClientHandler { UseCookies = false }; private static readonly HttpClient _httpClient = new HttpClient(_httpClientHandler); public RestApiClient(string apiAddress) { this.apiAddress = apiAddress; } private readonly string apiAddress; private string GetUrl(params string[] parts) { var partList = new List<string> { apiAddress.TrimEnd('/') }; partList.AddRange(parts.Where(part => !string.IsNullOrEmpty(part)).Select(part => part.TrimStart('/'))); return string.Join("/", partList); } public async Task<RestApiResponse<T>> Request<T>(RequestSettings requestSettings, params string[] parts) { var uri = GetUrl(parts); var requestMessage = new HttpRequestMessage(requestSettings.Method, uri); if (!string.IsNullOrEmpty(BearerToken)) { requestMessage.Headers.Add(AuthorizationHeader, $"Bearer {BearerToken}"); } foreach (var header in requestSettings.Headers) { requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value); } if (requestSettings.Content != null) { var contentString = (requestSettings.Content is string) ? requestSettings.Content as string : JsonConvert.SerializeObject(requestSettings.Content); if (!string.IsNullOrEmpty(contentString)) { requestMessage.Content = new StringContent(contentString, Encoding.UTF8, requestSettings.ContentType); } } var startTime = DateTime.Now; var responseMessage = await _httpClient.SendAsync(requestMessage); var responseContent = await responseMessage.Content.ReadAsStringAsync(); var duration = DateTime.Now - startTime; if (responseMessage.StatusCode == HttpStatusCode.Unauthorized) { throw new UnauthorizedAccessException($"Unauthorized; Url: {uri}"); } else if (requestSettings.ThrowOnErrorStatus && !responseMessage.IsSuccessStatusCode) { throw new Exception($"[{uri}]\r\n[Error, status not expected: {responseMessage.StatusCode}]\r\n{responseContent}"); } if (typeof(T) != typeof(string)) { T result = default; try { result = JsonConvert.DeserializeObject<T>(responseContent); } catch (Exception) { /* ignore */ } return new RestApiResponse<T>(uri, responseMessage, duration, responseContent, result); } // Return the request content as string return new RestApiResponse<T>(uri, responseMessage, duration, responseContent, (T)Convert.ChangeType(responseContent, typeof(T))); } public async Task<RestApiResponse<T>> Do<T>(RequestSettings requestSettings, params string[] parts) => await Request<T>(requestSettings, parts); public async Task<RestApiResponse<T>> Get<T>(params string[] parts) => await Request<T>(new RequestSettings(HttpMethod.Get), parts); public async Task<RestApiResponse<T>> Post<T>(object content, params string[] parts) => await Request<T>(new RequestSettings(HttpMethod.Post, content), parts); public async Task<RestApiResponse<T>> Put<T>(object content, params string[] parts) => await Request<T>(new RequestSettings(HttpMethod.Put, content), parts); public async Task<RestApiResponse<T>> Delete<T>(params string[] parts) => await Request<T>(new RequestSettings(HttpMethod.Delete), parts); } }
268100cookie-checkC# RestApiClient