Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
SimpleServer - makes echo testing from .NET unit tests easier
using System.IO;
// modified from RestSharp unit tests https://github.com/restsharp/RestSharp/blob/master/RestSharp.IntegrationTests/Helpers/SimpleServer.cs
namespace UnitTesting
{
using System;
using System.Net;
using System.Security;
using System.Threading;
/// <summary>
/// Simple echo handler
/// </summary>
/// <remarks>via https://github.com/restsharp/RestSharp/blob/master/RestSharp.IntegrationTests/Helpers/SimpleServer.cs </remarks>
public class SimpleServer : IDisposable
{
private readonly HttpListener listener;
private readonly Action<HttpListenerContext> handler;
private Thread thread;
private SimpleServer(HttpListener listener, Action<HttpListenerContext> handler)
{
this.listener = listener;
this.handler = handler;
}
/// <summary>
/// Simple echo handler
/// <example>Usage: <code>
/// using (SimpleServer.Create(SimpleServer.ECHO_URL)) { /* make an http post to same url, get back what you sent */ }
/// </code></example>
/// </summary>
/// <remarks>via https://github.com/restsharp/RestSharp/blob/master/RestSharp.IntegrationTests/Helpers/SimpleServer.cs </remarks>
/// <param name="url"></param>
/// <param name="authenticationSchemes"></param>
/// <returns></returns>
public static SimpleServer Create(
string url,
AuthenticationSchemes authenticationSchemes = AuthenticationSchemes.Anonymous)
{
return Create(url, context => EchoHandler(context), authenticationSchemes);
}
/// <summary>
/// Simple echo handler
/// <example>Usage: <code>
/// using (SimpleServer.Create(SimpleServer.ECHO_URL, SimpleServer.QueryStringBasedContentAndContentTypeHandler)) { /* make an http post to same url, get back what you sent */ }
/// </code></example>
/// </summary>
/// <remarks>via https://github.com/restsharp/RestSharp/blob/master/RestSharp.IntegrationTests/Helpers/SimpleServer.cs </remarks>
/// <param name="url"></param>
/// <param name="handler"></param>
/// <param name="authenticationSchemes"></param>
/// <returns></returns>
public static SimpleServer Create(
string url,
Action<HttpListenerContext> handler,
AuthenticationSchemes authenticationSchemes = AuthenticationSchemes.Anonymous)
{
var listener = new HttpListener { Prefixes = { url }, AuthenticationSchemes = authenticationSchemes };
var server = new SimpleServer(listener, handler);
server.Start();
return server;
}
public void Start()
{
if (this.listener.IsListening)
{
return;
}
this.listener.Start();
this.thread = new Thread(() => {
var context = this.listener.GetContext();
if(this.handler != null) this.handler(context);
context.Response.Close();
}) { Name = "WebServer" };
this.thread.Start();
}
public void Dispose()
{
try
{
this.thread.Abort();
}
catch (ThreadStateException threadStateException)
{
Console.WriteLine("Issue aborting thread - {0}.", threadStateException.Message);
}
catch (SecurityException securityException)
{
Console.WriteLine("Issue aborting thread - {0}.", securityException.Message);
}
if (this.listener.IsListening)
{
try
{
this.listener.Stop();
}
catch (ObjectDisposedException objectDisposedException)
{
Console.WriteLine("Issue stopping listener - {0}", objectDisposedException.Message);
}
}
this.listener.Close();
}
/// <summary>
/// Handler helper that takes the content type, content from the querystring ("ct" and "c", respectively)
/// </summary>
/// <param name="obj"></param>
public static void QueryStringBasedContentAndContentTypeHandler(HttpListenerContext obj)
{
QueryStringBasedContentAndContentTypeHandler(obj, "ct", "c", 200);
}
/// <summary>
/// Handler helper that takes the content type/content from the querystring
/// </summary>
/// <param name="obj"></param>
/// <param name="paramContentType"></param>
/// <param name="paramContent"></param>
/// <param name="statusCode"></param>
public static void QueryStringBasedContentAndContentTypeHandler(HttpListenerContext obj, string paramContentType, string paramContent, int statusCode)
{
var contentType = obj.Request.QueryString[paramContentType];
if( ! string.IsNullOrWhiteSpace(contentType) ) obj.Response.ContentType = contentType;
var content = obj.Request.QueryString[paramContent];
if(null != content)
using(var sw = new StreamWriter(obj.Response.OutputStream))
sw.Write(content);
obj.Response.StatusCode = statusCode;
}
/// <summary>
/// Handler helper that just dumps what was sent
/// </summary>
/// <param name="obj"></param>
/// <param name="statusCode"></param>
/// <param name="contentIsNthAcceptType">Which accept type should be used as the content type?</param>
public static void EchoHandler(HttpListenerContext obj, int statusCode = 200, int contentIsNthAcceptType = 0)
{
obj.Response.ContentType = obj.Request.AcceptTypes == null || obj.Request.AcceptTypes.Length == 0 ? obj.Request.ContentType : obj.Request.AcceptTypes[contentIsNthAcceptType];
string content = null;
using (var sr = new StreamReader(obj.Request.InputStream)) content = sr.ReadToEnd();
if (null != content)
using (var sw = new StreamWriter(obj.Response.OutputStream))
sw.Write(content);
obj.Response.StatusCode = statusCode;
}
/// <summary>
/// Can use to return what you sent, for testing.
/// </summary>
public const string ECHO_URL = "http://localhost:8080/";
/// <summary>
/// Returns what you sent, for testing. If Fiddler is enabled, this will be an echo service.
/// </summary>
public const string FIDDLER_ECHO_URL = "http://localhost:8888/";
}
}
@zaus

This comment has been minimized.

Copy link

zaus commented Jul 10, 2015

d'oh

@zaus

This comment has been minimized.

Copy link

zaus commented Jul 10, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.