Last active
March 26, 2021 10:34
-
-
Save ian-beer/6247d20642e789db211c3def6624c5bc to your computer and use it in GitHub Desktop.
.Net RestClient
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
using System.Collections.Generic; | |
using System.Collections.Specialized; | |
using System.Linq; | |
using System.Net.Http.Headers; | |
using Newtonsoft.Json.Linq; | |
namespace HttpUtils | |
{ | |
public static class RestClient | |
{ | |
public static async Task<HttpResponseMessage> Get(string url, IDictionary<string, string> headers) | |
{ | |
return await Send(BuildRequestMessage(HttpMethod.Get, url, headers)); | |
} | |
public static async Task<HttpResponseMessage> Post(string url, IDictionary<string, string> headers) | |
{ | |
return await Send(BuildRequestMessage(HttpMethod.Post, url, headers)); | |
} | |
public static async Task<HttpResponseMessage> Post(string url, IDictionary<string, string> headers, string content) | |
{ | |
return await Send(BuildRequestMessage(HttpMethod.Post, url, headers, content)); | |
} | |
private static async Task<HttpResponseMessage> Send(HttpRequestMessage request) | |
{ | |
using (var client = new HttpClient()) | |
{ | |
var response = await client.SendAsync(request); | |
if (response.IsSuccessStatusCode) | |
{ | |
return response; | |
} | |
var responseContent = await response.Content.ReadAsStringAsync(); | |
throw new HttpRequestException($"error occured in RestClient when calling: request: {request.RequestUri} statusCode: {response.StatusCode}", new Exception(responseContent)); | |
} | |
} | |
private static HttpRequestMessage BuildRequestMessage(HttpMethod method, string url, | |
IDictionary<string, string> headers, string jsonString = null) | |
{ | |
var request = new HttpRequestMessage | |
{ | |
RequestUri = new Uri(url), | |
Method = method, | |
}; | |
foreach (var header in headers) | |
{ | |
request.Headers.Add(header.Key, header.Value); | |
} | |
if (jsonString != null) | |
{ | |
request.Content = new StringContent(jsonString); | |
} | |
return request; | |
} | |
} | |
public static class HttpUtils | |
{ | |
public static JObject FormDataToJson(this NameValueCollection data) | |
{ | |
var json = new JObject(); | |
for (var i = 0; i < data.Count; i++) | |
{ | |
var key = data.GetKey(i); | |
var value = data.GetValues(key); | |
json.Add(key, value?[0]); | |
} | |
return json; | |
} | |
public static KeyValuePair<string, string> BuildXAuthHeader(string authToken) | |
{ | |
return new KeyValuePair<string, string>("X-Auth-Token", authToken); | |
} | |
public static KeyValuePair<string, string> BuildBasicAuthHeader(string username, string password) | |
{ | |
var encodedCredentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}")); | |
return new KeyValuePair<string, string>("Authorization", $"Basic {encodedCredentials}"); | |
} | |
public static IDictionary<string, string> BuildXAuthHeaderDictionary(string authToken) | |
{ | |
var authHeader = BuildXAuthHeader(authToken); | |
return new Dictionary<string, string> { { authHeader.Key, authHeader.Value } }; | |
} | |
public static IDictionary<string, string> BuildBasicAuthHeaderDictionary(string username, string password) | |
{ | |
var authHeader = BuildBasicAuthHeader(username, password); | |
return new Dictionary<string, string> { { authHeader.Key, authHeader.Value } }; | |
} | |
/// <summary> | |
/// Check the Link header for a rel='next' ini. If present return ini link. | |
/// </summary> | |
/// <param name="headers"></param> | |
/// <returns></returns> | |
public static string GetNextResource(HttpResponseHeaders headers) | |
{ | |
var linkHeader = headers.SingleOrDefault(h => h.Key.ToLowerInvariant() == "link"); | |
if (linkHeader.Key == null) | |
{ | |
return null; | |
} | |
var linkHeaderDictionary = ParseLinkHeader(linkHeader.Value.SingleOrDefault()); | |
return linkHeaderDictionary.ContainsKey("rel='next'") ? linkHeaderDictionary["rel='next'"] : null; | |
} | |
/// <summary> | |
/// The link header contains related iris for deep crawl api | |
/// ex: | |
/// { </accounts/41358/projects/263913/crawls/1882279/reports?page=1&per_page=200&sort=id>; rel='first', | |
/// </accounts/41358/projects/263913/crawls/1882279/reports?page=2&per_page=200&sort=id>; rel='last', | |
/// </accounts/41358/projects/263913/crawls/1882279/reports?page=2&per_page=200&sort=id>; rel='next' } | |
/// | |
/// because of pagination we need to parse this data for the 'next' iri. | |
/// | |
/// see: https://tools.ietf.org/html/rfc3987, https://tools.ietf.org/html/rfc5988#page-6 | |
/// </summary> | |
/// <param name="headerValue"></param> | |
/// <returns></returns> | |
public static Dictionary<string,string> ParseLinkHeader(string headerValue) | |
{ | |
return headerValue.Split(',').ToDictionary(l => | |
{ | |
var iniSplit = l.Split(';'); | |
return iniSplit[1].Trim(); | |
}, l => | |
{ | |
var iniSplit = l.Split(';'); | |
var link = iniSplit[0].Trim(); | |
var cleanLink = link.Trim('<', '>'); | |
return cleanLink; | |
}); | |
} | |
/// <summary> | |
/// Use this if your url or injectable partial of a url may contain special characters | |
/// NOTE: this was made for an Azure Function. Utilizes the wrong library for .Net web apps. | |
/// see: https://docs.microsoft.com/en-us/dotnet/api/system.web.httputility.urlencode?view=netframework-4.6.1 | |
/// </summary> | |
/// <param name="urlOrPartial">full Url or any partial of an url</param> | |
/// <returns></returns> | |
public static string EncodeUrlOrPartial(string urlOrPartial) | |
{ | |
return System.Net.WebUtility.HtmlEncode(urlOrPartial); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment