Created
June 17, 2014 12:22
-
-
Save xanathar/e8f7cf7410a5ff479292 to your computer and use it in GitHub Desktop.
HttpListener #1
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
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