Skip to content

Instantly share code, notes, and snippets.

@zaus
Forked from anonymous/SimpleServer.cs
Last active August 29, 2015 14:24
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 zaus/dc7027583e85018cd91e to your computer and use it in GitHub Desktop.
Save zaus/dc7027583e85018cd91e to your computer and use it in GitHub Desktop.
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
Copy link
Author

zaus commented Jul 10, 2015

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