private static void HttpListenHandler(IAsyncResult result) { HttpListenerContext context = null; if (HttpListener == null) { return; } if (result != ApiListener.result) { return; } try { context = HttpListener.EndGetContext(result); string body = null; if (context.Request.HasEntityBody) { using (System.IO.Stream bodyStream = context.Request.InputStream) { using (System.IO.StreamReader reader = new System.IO.StreamReader(bodyStream, context.Request.ContentEncoding)) { body = reader.ReadToEnd(); } } } byte[] responseBuffer; var response = "ok"; string command = "Unknown Command"; try { var urlParams = new List <string>(context.Request.RawUrl.Split(new char[] { '/' })).Select(us => Uri.UnescapeDataString(us)).ToList(); if (!string.IsNullOrWhiteSpace(body)) { urlParams.Add(body); } if (string.IsNullOrWhiteSpace(urlParams.FirstOrDefault())) { urlParams.RemoveAt(0); } if (string.IsNullOrWhiteSpace(urlParams.LastOrDefault()) && urlParams.Any()) { urlParams.RemoveAt(urlParams.Count - 1); } if (!urlParams.Any()) { response = Documentation.Function(null); } else if (urlParams[0] == "favicon.ico") { context.Response.StatusCode = 404; response = "Not found."; } else { command = urlParams[0]; urlParams.RemoveAt(0); if (!Commands.ContainsKey(command)) { throw new ApiError($"Invalid Command \"{command}\""); } command = Commands[command]?.Name; //normalize name for display during errors response = Commands[command].Function(urlParams) ?? response; } } catch (Exception e) { response = $"{command}: {e.Message}"; context.Response.StatusCode = e is ApiError ? 400 : 500; } responseBuffer = Encoding.UTF8.GetBytes(response); context.Response.ContentType = "application/json; charset=utf-8"; // Get a response stream and write the response to it. context.Response.ContentLength64 = responseBuffer.Length; using (System.IO.Stream output = context.Response.OutputStream) { output.Write(responseBuffer, 0, responseBuffer.Length); output.Close(); } Log(Debug($"{context.Request.RawUrl} => {context.Response.StatusCode}: {response}")); } catch (Exception e) { Log(Critical($"{context?.Request?.RawUrl ?? "(Error getting accessed URL)"} => {e.Message}")); } finally { try { if (HttpListener.IsListening) { Listen(); } } catch (ObjectDisposedException) { } } }