Skip to content

Instantly share code, notes, and snippets.

@KKings
Created January 27, 2017 20:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KKings/874bbe8b9c70750cdd80d942d34bc6e4 to your computer and use it in GitHub Desktop.
Save KKings/874bbe8b9c70750cdd80d942d34bc6e4 to your computer and use it in GitHub Desktop.
Unit Testable Service for making HttpRequests
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);
}
}
}
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);
}
}
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);
}
}
namespace Example
{
public interface ISerializer
{
string Serialize<T>(T value);
T Deserialize<T>(string value);
}
}
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);
}
}
}
@KKings
Copy link
Author

KKings commented Jan 27, 2017

Example uses NewtonSoft library to serialize/deserialize requests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment