Created
June 22, 2014 20:18
-
-
Save dbones/76073f272e6e60c66411 to your computer and use it in GitHub Desktop.
a wrapper around the webrequest, using a connection style. because i can
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 HttpJsonTest | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Net; | |
using System.Text; | |
using System.Web; | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
//http://192.168.1.123:5984/test_suite_db/_all_docs | |
var connection = new Connection("http://192.168.1.123:5984"); | |
var request = new Request("/:db/_all_docs", HttpVerbType.Get); | |
request.AddUrlSegment("db", "test_suite_db"); | |
connection.Execute(request, response => Console.Write(response.Content.ReadToEnd())); | |
Console.Read(); | |
} | |
} | |
/// <summary> | |
/// Auth mechanism to be applied on the http connection | |
/// </summary> | |
public interface IAuthentication | |
{ | |
void Apply(IRequest request); | |
} | |
/// <summary> | |
/// RFC 2617 | |
/// </summary> | |
public class BasicAuthentication : IAuthentication | |
{ | |
private string authHeader; | |
public BasicAuthentication(string userName, string password) | |
{ | |
var encoded = Convert.ToBase64String(Encoding.Default.GetBytes(userName + ":" + password)); | |
authHeader = "Basic " + encoded; | |
} | |
public void Apply(IRequest request) | |
{ | |
request.AddHeader("Authorization", authHeader); | |
} | |
} | |
/// <summary> | |
/// RFC 2109 | |
/// </summary> | |
public class CookieAuthentication : IAuthentication | |
{ | |
private Cookie _authSession; | |
public CookieAuthentication( | |
string serverUrl, | |
string userName, | |
string password) | |
{ | |
var connection = new Connection(serverUrl); | |
var request = new FormRequest("/_session", HttpVerbType.Post); | |
request.AddFormParameter("name", userName); | |
request.AddFormParameter("password", password); | |
connection.Execute(request, response => | |
{ | |
if (response.Status == HttpStatusCode.OK) | |
{ | |
_authSession = response.Cookies["AuthSession"]; | |
} | |
}); | |
} | |
public void Apply(IRequest request) | |
{ | |
request.AddCookie(_authSession); | |
} | |
} | |
public interface IConnection | |
{ | |
/// <summary> | |
/// set the authentication to use for all request on this connection | |
/// </summary> | |
IAuthentication Authentication { get; set; } | |
/// <summary> | |
/// set the proxy to use for this connection | |
/// </summary> | |
/// <remarks> | |
/// setting it to null will make the connection faster | |
/// </remarks> | |
IWebProxy Proxy { get; set; } | |
/// <summary> | |
/// Execute a command against this connection/endpoint | |
/// </summary> | |
/// <param name="request">request to execute</param> | |
/// <param name="responseHandler"></param> | |
void Execute(IRequest request, Action<IResponse> responseHandler); | |
} | |
public interface IRequest | |
{ | |
IWebProxy Proxy { get; set; } | |
void Execute(string baseUrl, Action<Response> handleRequest, IWebProxy proxy = null); | |
void AddHeader(string key, string header); | |
void AddCookie(Cookie cookie); | |
void AddParameter(string key, string value); | |
void AddUrlSegment(string key, string value); | |
void AddContent(Action<StreamWriter> writeConent, HttpContentType contentType); | |
} | |
public interface IResponse | |
{ | |
HttpStatusCode Status { get; } | |
StreamReader Content { get; } | |
long NumberOfBytes { get; } | |
CookieCollection Cookies { get; set; } | |
WebHeaderCollection Headers { get; } | |
} | |
public class Connection : IConnection | |
{ | |
private readonly string _baseUrl; | |
public Connection(string baseUrl) | |
{ | |
_baseUrl = baseUrl; | |
} | |
public IAuthentication Authentication { get; set; } | |
public IWebProxy Proxy { get; set; } | |
public void Execute(IRequest request, Action<IResponse> responseHandler) | |
{ | |
try | |
{ | |
if (Authentication != null) | |
{ | |
Authentication.Apply(request); | |
} | |
request.Execute(_baseUrl, responseHandler, Proxy); | |
} | |
catch (Exception ex) | |
{ | |
throw new RequestException(request, ex); | |
} | |
} | |
} | |
public class Request : IRequest | |
{ | |
protected string _url; | |
protected readonly List<string> _params = new List<string>(); | |
protected readonly List<Action<HttpWebRequest>> _configs = new List<Action<HttpWebRequest>>(); | |
protected Action<StreamWriter> _writeContent; | |
protected HttpVerbType _httpVerb = HttpVerbType.Get; | |
public Request(string url, HttpVerbType verbType) | |
{ | |
_url = url; | |
SetVerb(verbType); | |
} | |
public virtual IWebProxy Proxy { get; set; } | |
public virtual void Execute(string baseUrl, Action<Response> handleRequest, IWebProxy proxy = null) | |
{ | |
string url = CreateUrl(baseUrl); | |
var request = (HttpWebRequest)WebRequest.Create(url); | |
request.Proxy = proxy ?? Proxy; | |
Setup(request); | |
request.AutomaticDecompression = | |
DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.None; | |
if (_httpVerb != HttpVerbType.Get) | |
{ | |
using (var streamWriter = new StreamWriter(request.GetRequestStream())) | |
{ | |
_writeContent(streamWriter); | |
} | |
} | |
using (var httpResponse = (HttpWebResponse) request.GetResponse()) | |
{ | |
var stream = httpResponse.GetResponseStream(); | |
if (stream == null) | |
{ | |
var response = new Response(httpResponse); | |
handleRequest(response); | |
} | |
else | |
{ | |
using (var contentReader = new StreamReader(stream)) | |
{ | |
var response = new Response(httpResponse, contentReader); | |
handleRequest(response); | |
} | |
} | |
} | |
} | |
public virtual void AddHeader(string key, string header) | |
{ | |
_configs.Add(request => request.Headers.Add(key, header)); | |
} | |
public void AddCookie(Cookie cookie) | |
{ | |
_configs.Add(request => request.CookieContainer.Add(cookie)); | |
} | |
public virtual void AddParameter(string key, string value) | |
{ | |
var encoded = HttpUtility.UrlEncode(value); | |
_params.Add(string.Format("{0}={1}", key, encoded)); | |
} | |
public virtual void AddUrlSegment(string key, string value) | |
{ | |
var encoded = HttpUtility.UrlEncode(value); | |
_url = _url.Replace(string.Format(":{0}", key), encoded); | |
} | |
public virtual void AddContent(Action<StreamWriter> writeConent, HttpContentType contentType) | |
{ | |
SetContentType(contentType); | |
_writeContent = writeConent; | |
} | |
private string CreateUrl(string baseUrl) | |
{ | |
var builder = new StringBuilder(); | |
builder.Append(baseUrl); | |
if (!string.IsNullOrWhiteSpace(_url)) | |
{ | |
//try and ensure there is a / | |
if (!baseUrl.EndsWith("/") && !_url.StartsWith("/")) | |
{ | |
builder.Append("/"); | |
} | |
builder.Append(_url); | |
} | |
if (_params.Any()) | |
{ | |
var @params = string.Join("&", _params); | |
builder.Append("?"); | |
builder.Append(@params); | |
} | |
return builder.ToString(); | |
} | |
private void Setup(HttpWebRequest request) | |
{ | |
foreach (var config in _configs) | |
{ | |
config(request); | |
} | |
} | |
protected void SetContentType(HttpContentType contentType) | |
{ | |
string value; | |
switch (contentType) | |
{ | |
case HttpContentType.Json: | |
value = "text/json"; | |
break; | |
case HttpContentType.Form: | |
value = "application/x-www-form-urlencoded"; | |
break; | |
default: | |
throw new ArgumentOutOfRangeException("contentType"); | |
} | |
_configs.Add(request => request.ContentType = value); | |
} | |
private void SetVerb(HttpVerbType verbType) | |
{ | |
_httpVerb = verbType; | |
string value; | |
switch (verbType) | |
{ | |
case HttpVerbType.Post: | |
value = "POST"; | |
break; | |
case HttpVerbType.Get: | |
value = "GET"; | |
break; | |
default: | |
throw new ArgumentOutOfRangeException("verbType"); | |
} | |
_configs.Add(request => request.Method = value); | |
} | |
} | |
public class FormRequest : Request | |
{ | |
protected List<string> _formParams = new List<string>(); | |
public FormRequest(string url, HttpVerbType verbType) : base(url, verbType) | |
{ | |
SetContentType(HttpContentType.Form); | |
if (verbType == HttpVerbType.Get) | |
{ | |
throw new NotSupportedException("cannot use Get verb"); | |
} | |
} | |
public override void Execute(string baseUrl, Action<Response> handleRequest, IWebProxy proxy = null) | |
{ | |
if (_formParams.Any()) | |
{ | |
_writeContent = writer => writer.Write(string.Join("&", _formParams)); | |
} | |
base.Execute(baseUrl, handleRequest, proxy); | |
} | |
public override void AddContent(Action<StreamWriter> writeConent, HttpContentType contentType) | |
{ | |
throw new NotImplementedException("use AddFormParameter"); | |
} | |
public virtual void AddFormParameter(string key, string value) | |
{ | |
var encoded = HttpUtility.UrlEncode(value); | |
_formParams.Add(string.Format("{0}={1}", key, encoded)); | |
} | |
} | |
public class Response : IResponse | |
{ | |
public Response(HttpWebResponse response, StreamReader contentReader = null) | |
{ | |
Content = contentReader; | |
Status = response.StatusCode; | |
NumberOfBytes = response.ContentLength; | |
Headers = response.Headers; | |
Cookies = response.Cookies; | |
} | |
public CookieCollection Cookies { get; set; } | |
public WebHeaderCollection Headers { get; private set; } | |
public HttpStatusCode Status { get; private set; } | |
public StreamReader Content { get; private set; } | |
public long NumberOfBytes { get; private set; } | |
} | |
public enum HttpVerbType | |
{ | |
Post, | |
Get | |
} | |
public enum HttpContentType | |
{ | |
Json, | |
Xml, | |
Form | |
} | |
public class RequestException : Exception | |
{ | |
public RequestException(IRequest request) | |
{ | |
Request = request; | |
} | |
public RequestException(IRequest request, Exception innerException) | |
: base("", innerException) | |
{ | |
Request = request; | |
} | |
public IRequest Request { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment