Created
January 27, 2017 20:14
-
-
Save KKings/874bbe8b9c70750cdd80d942d34bc6e4 to your computer and use it in GitHub Desktop.
Unit Testable Service for making HttpRequests
This file contains 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
namespace Example | |
{ | |
using System; | |
using System.IO; | |
using System.Net; | |
using System.Text; | |
using System.Threading.Tasks; | |
using Abstractions; | |
public class HttpService : IHttpService | |
{ | |
/// <summary> | |
/// Logging Implementation | |
/// </summary> | |
private readonly ILog logger; | |
/// <summary> | |
/// Serializer for converting objects to strings and strings to objects | |
/// </summary> | |
private readonly ISerializer serializer; | |
public HttpService(ILog logger, ISerializer serializer) | |
{ | |
this.logger = logger; | |
this.serializer = serializer; | |
} | |
/// <summary> | |
/// Creates the Web Request | |
/// </summary> | |
/// <param name="uri">The Uri</param> | |
/// <returns>Instance of <see cref="HttpWebRequest"/></returns> | |
public virtual HttpWebRequest CreateWebRequest(Uri uri) | |
{ | |
return (HttpWebRequest)WebRequest.Create(uri); | |
} | |
/// <summary> | |
/// Synchronous GET to a <see cref="Uri"/> | |
/// </summary> | |
/// <param name="uri">The Uri</param> | |
/// <returns>Instance of <see cref="T"/></returns> | |
public virtual T Get<T>(Uri uri) | |
{ | |
var httpWebRequest = this.CreateWebRequest(uri); | |
httpWebRequest.Method = "GET"; | |
httpWebRequest.AllowAutoRedirect = true; | |
httpWebRequest.Timeout = 30 * 1000; | |
try | |
{ | |
using (var response = httpWebRequest.GetResponse() as HttpWebResponse) | |
// ReSharper disable once PossibleNullReferenceException | |
using (var responseStream = response.GetResponseStream()) | |
{ | |
// ReSharper disable once AssignNullToNotNullAttribute | |
var value = new StreamReader(responseStream).ReadToEnd(); | |
return this.serializer.Deserialize<T>(value); | |
} | |
} | |
catch (WebException webException) // Anything other than a 200 series | |
{ | |
this.logger.Error($"GET Request returned a non 200 status: {webException}", this); | |
var response = (HttpWebResponse)webException.Response; | |
using (var responseStream = response.GetResponseStream()) | |
{ | |
var value = new StreamReader(responseStream).ReadToEnd(); | |
return this.serializer.Deserialize<T>(value); | |
} | |
} | |
catch (Exception exception) | |
{ | |
this.logger.Error($"GET Request failed: {exception}", this); | |
} | |
return default(T); | |
} | |
/// <summary> | |
/// Asynchronous GET to a <see cref="Uri"/> | |
/// </summary> | |
/// <param name="uri">The Uri</param> | |
/// <returns>Instance of <see cref="T"/></returns> | |
public virtual async Task<T> GetAsync<T>(Uri uri) | |
{ | |
var httpWebRequest = this.CreateWebRequest(uri); | |
httpWebRequest.Method = "GET"; | |
httpWebRequest.AllowAutoRedirect = true; | |
httpWebRequest.Timeout = 30 * 1000; | |
try | |
{ | |
using (var response = httpWebRequest.GetResponse() as HttpWebResponse) | |
// ReSharper disable once PossibleNullReferenceException | |
using (var responseStream = response.GetResponseStream()) | |
{ | |
// ReSharper disable once AssignNullToNotNullAttribute | |
var value = await new StreamReader(responseStream).ReadToEndAsync(); | |
return this.serializer.Deserialize<T>(value); | |
} | |
} | |
catch (WebException webException) // Anything other than a 200 series | |
{ | |
this.logger.Error($"GET Request returned a non 200 status: {webException}", this); | |
var response = (HttpWebResponse)webException.Response; | |
using (var responseStream = response.GetResponseStream()) | |
{ | |
var value = await new StreamReader(responseStream).ReadToEndAsync(); | |
return this.serializer.Deserialize<T>(value); | |
} | |
} | |
catch (Exception exception) | |
{ | |
this.logger.Error($"Async GET Request failed: {exception}", this); | |
} | |
return default(T); | |
} | |
/// <summary> | |
/// Synchronous POST to a <see cref="Uri"/> | |
/// </summary> | |
/// <param name="uri">The Uri</param> | |
/// <param name="data">The data to send in the stream</param> | |
/// <param name="contentType">The content type of the stream</param> | |
/// <returns>Instance of <see cref="T"/></returns> | |
public virtual T Post<T>(Uri uri, object data, string contentType = "application/json") | |
{ | |
var httpWebRequest = this.CreateWebRequest(uri); | |
httpWebRequest.Method = "POST"; | |
httpWebRequest.Timeout = 30 * 1000; | |
httpWebRequest.ContentType = contentType; | |
var s = data as string; | |
var stringy = s ?? this.serializer.Serialize(data); | |
var bytes = Encoding.UTF8.GetBytes(stringy); | |
httpWebRequest.ContentLength = stringy.Length; | |
try | |
{ | |
var requestStream = httpWebRequest.GetRequestStream(); | |
requestStream.Write(bytes, 0, bytes.Length); | |
requestStream.Close(); | |
using (var response = httpWebRequest.GetResponse() as HttpWebResponse) | |
using (var responseStream = response.GetResponseStream()) | |
{ | |
var value = new StreamReader(responseStream).ReadToEnd(); | |
return this.serializer.Deserialize<T>(value); | |
} | |
} | |
catch (WebException webException) // Anything other than a 200 series | |
{ | |
this.logger.Error($"POST Request returned a non 200 status: {webException}", this); | |
var response = (HttpWebResponse)webException.Response; | |
using (var responseStream = response.GetResponseStream()) | |
{ | |
var value = new StreamReader(responseStream).ReadToEnd(); | |
return this.serializer.Deserialize<T>(value); | |
} | |
} | |
catch (Exception exception) | |
{ | |
this.logger.Error($"POST Request Failed: {exception}", this); | |
} | |
return default(T); | |
} | |
/// <summary> | |
/// Asynchronous POST to a <see cref="Uri"/> | |
/// </summary> | |
/// <param name="uri">The Uri</param> | |
/// <param name="data">The data to send in the stream</param> | |
/// <param name="contentType">The content type of the stream</param> | |
/// <returns>Instance of <see cref="T"/></returns> | |
public virtual async Task<T> PostAsync<T>(Uri uri, object data, string contentType = "application/json") | |
{ | |
var httpWebRequest = this.CreateWebRequest(uri); | |
httpWebRequest.Method = "POST"; | |
httpWebRequest.Timeout = 30 * 1000; | |
httpWebRequest.ContentType = contentType; | |
var s = data as string; | |
var stringy = s ?? this.serializer.Serialize(data); | |
var bytes = Encoding.UTF8.GetBytes(stringy); | |
httpWebRequest.ContentLength = stringy.Length; | |
try | |
{ | |
var requestStream = httpWebRequest.GetRequestStream(); | |
requestStream.Write(bytes, 0, bytes.Length); | |
requestStream.Close(); | |
using (var response = httpWebRequest.GetResponse() as HttpWebResponse) | |
using (var responseStream = response.GetResponseStream()) | |
{ | |
var value = await new StreamReader(responseStream).ReadToEndAsync(); | |
return this.serializer.Deserialize<T>(value); | |
} | |
} | |
catch (WebException webException) // Anything other than a 200 series | |
{ | |
this.logger.Error($"POST Request returned a non 200 status: {webException}", this); | |
var response = (HttpWebResponse)webException.Response; | |
using (var responseStream = response.GetResponseStream()) | |
{ | |
var value = new StreamReader(responseStream).ReadToEnd(); | |
return this.serializer.Deserialize<T>(value); | |
} | |
} | |
catch (Exception exception) | |
{ | |
this.logger.Error($"POST Request Failed: {exception}", this); | |
} | |
return default(T); | |
} | |
} | |
} |
This file contains 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
namespace Example | |
{ | |
using System; | |
using System.Threading.Tasks; | |
public interface IHttpService | |
{ | |
T Get<T>(Uri uri); | |
Task<T> GetAsync<T>(Uri uri); | |
T Post<T>(Uri uri, object data, string contentType); | |
Task<T> PostAsync<T>(Uri uri, object data, string contentType); | |
} | |
} |
This file contains 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
namespace Example | |
{ | |
public interface ILog | |
{ | |
void Debug(string message, object owner); | |
void Info(string message, object owner); | |
void Warn(string message, object owner); | |
void Error(string message, object owner); | |
} | |
} |
This file contains 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
namespace Example | |
{ | |
public interface ISerializer | |
{ | |
string Serialize<T>(T value); | |
T Deserialize<T>(string value); | |
} | |
} |
This file contains 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
namespace Example | |
{ | |
using System; | |
using Newtonsoft.Json; | |
public class JsonSerializer : ISerializer | |
{ | |
/// <summary> | |
/// Serializes a string into an object of type <see cref="T"/> | |
/// </summary> | |
/// <param name="value">The value</param> | |
/// <returns>String representation of type <see cref="T"/></returns> | |
public string Serialize<T>(T value) | |
{ | |
return JsonConvert.SerializeObject(value); | |
} | |
/// <summary> | |
/// Deserializes a string into an object of type <see cref="T"/> | |
/// </summary> | |
/// <param name="value">The value is serialize</param> | |
/// <returns>Object of type <see cref="T"/></returns> | |
public T Deserialize<T>(string value) | |
{ | |
return String.IsNullOrEmpty(value) ? default(T) : JsonConvert.DeserializeObject<T>(value); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example uses NewtonSoft library to serialize/deserialize requests