Skip to content

Instantly share code, notes, and snippets.

@xanathar
Created June 17, 2014 12:22
Show Gist options
  • Save xanathar/e8f7cf7410a5ff479292 to your computer and use it in GitHub Desktop.
Save xanathar/e8f7cf7410a5ff479292 to your computer and use it in GitHub Desktop.
HttpListener #1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Diagnostics;
using System.IO;
using System.Web;
using System.Collections.Specialized;
using System.Xml;
namespace ...
{
/// <summary>
/// A class implementing a parallel HTTP listener
/// </summary>
public class ThreadedHttpListener
{
int m_Port = 80;
string[] m_UriPrefixes;
Thread m_HttpThread;
Thread m_AbortThread;
HttpListener m_Listener = null;
CancellationToken m_Token;
const int MAXTIMEOUT = 500;
object abortLock = new object();
bool isAborted = false;
/// <summary>
/// Initializes a new instance of the <see cref="ThreadedHttpListener"/> class.
/// </summary>
/// <param name="port">The port.</param>
/// <param name="prefixes">The URL prefixes.</param>
public ThreadedHttpListener(int port, params string[] prefixes)
{
m_Port = port;
m_UriPrefixes = prefixes;
}
/// <summary>
/// Starts the thread with the specified cancellation token.
/// </summary>
public void Start(CancellationToken token)
{
m_Token = token;
isAborted = false;
m_Listener = new HttpListener();
foreach (string prefix in m_UriPrefixes)
m_Listener.Prefixes.Add(prefix);
m_Listener.Start();
m_HttpThread = new Thread(HttpListen);
m_HttpThread.Name = "HttpListener";
m_HttpThread.IsBackground = true;
m_HttpThread.Start();
m_AbortThread = new Thread(Aborter);
m_AbortThread.Name = "HttpListener_Aborter";
m_AbortThread.IsBackground = true;
m_AbortThread.Start();
}
private void HttpListen()
{
while (!m_Token.IsCancellationRequested)
{
try
{
HttpListenerContext context = m_Listener.GetContext();
if (m_Token.IsCancellationRequested)
break;
lock (abortLock)
{
Logger.WriteLine("Request received from {0}", context.Request.RemoteEndPoint.Address);
ProcessRequestReceived(context);
}
}
catch (HttpListenerException)
{
lock (abortLock)
{
if (!isAborted)
{
throw;
}
}
}
}
lock (abortLock)
{
if (!isAborted)
{
m_Listener.Stop();
isAborted = true;
}
}
}
private void Aborter()
{
m_Token.WaitHandle.WaitOne();
lock (abortLock)
{
if (!isAborted)
{
isAborted = true;
m_Listener.Abort();
}
}
}
public event EventHandler<HttpRequestEventArgs> RequestReceived;
private void ProcessRequestReceived(HttpListenerContext context)
{
bool handled = false;
try
{
NameValueCollection parameters;
string extraContent, pageName;
ParseParameters(context.Request, out parameters, out extraContent, out pageName);
...
handled = true;
}
catch (Exception ex)
{
context.Response.StatusCode = 500;
SendString(ex.ToString(), context.Response);
handled = true;
Logger.WriteLine("Exception: {0}", ex.ToString());
}
if (!handled)
{
context.Response.StatusCode = 404;
context.Response.Close();
Logger.WriteLine("Unhandled request");
}
}
public static void SendString(string responseString, HttpListenerResponse response)
{
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
using (Stream output = response.OutputStream)
{
output.Write(buffer, 0, buffer.Length);
output.Close();
}
}
private void ParseParameters(HttpListenerRequest request, out NameValueCollection variables, out string extraContent, out string pageName)
{
variables = null;
extraContent = null;
string[] urlComponents = request.RawUrl.Split(new char[] { '?' });
pageName = urlComponents[0];
if (!request.HasEntityBody)
{
variables = request.QueryString;
}
else
{
using (Stream body = request.InputStream)
{
using (StreamReader reader = new StreamReader(body, request.ContentEncoding))
{
string postString = reader.ReadToEnd();
if (request.ContentType.ToLower() == "application/x-www-form-urlencoded")
{
variables = HttpUtility.ParseQueryString(postString, request.ContentEncoding);
}
else
{
variables = request.QueryString;
extraContent = postString;
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment