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