2015-08-21 21:14:02 -04:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2017-05-26 18:49:27 -04:00
|
|
|
|
using System.Collections.Specialized;
|
2015-08-21 21:14:02 -04:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using Kayak.Http;
|
2017-05-26 18:49:27 -04:00
|
|
|
|
using Kayak;
|
2015-08-21 21:14:02 -04:00
|
|
|
|
|
2015-08-23 17:58:48 -04:00
|
|
|
|
|
2017-05-26 18:49:27 -04:00
|
|
|
|
namespace IW4MAdmin
|
|
|
|
|
{
|
2017-05-27 00:22:50 -04:00
|
|
|
|
class Scheduler : ISchedulerDelegate
|
2015-08-21 21:14:02 -04:00
|
|
|
|
{
|
|
|
|
|
public void OnException(IScheduler scheduler, Exception e)
|
|
|
|
|
{
|
2017-06-12 13:50:00 -04:00
|
|
|
|
// it looks like there's a library error in
|
|
|
|
|
// Kayak.Http.HttpServerTransactionDelegate.OnError
|
2017-11-14 16:36:55 -05:00
|
|
|
|
if ((uint)e.HResult == 0x80004003 || (uint)e.InnerException?.HResult == 0x80004003)
|
2017-06-12 13:50:00 -04:00
|
|
|
|
return;
|
|
|
|
|
|
2017-06-19 13:58:01 -04:00
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteWarning("Web service has encountered an error - " + e.Message);
|
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
|
2017-05-30 17:23:31 -04:00
|
|
|
|
|
|
|
|
|
if (e.InnerException != null)
|
|
|
|
|
{
|
2017-06-19 13:58:01 -04:00
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteDebug($"Inner Exception: {e.InnerException.Message}");
|
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteDebug($"Inner Stack Trace: {e.InnerException.StackTrace}");
|
2017-05-30 17:23:31 -04:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-21 21:14:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnStop(IScheduler scheduler)
|
|
|
|
|
{
|
2017-06-19 13:58:01 -04:00
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteInfo("Web service has been stopped...");
|
2015-08-21 21:14:02 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-26 18:49:27 -04:00
|
|
|
|
class Request : IHttpRequestDelegate
|
2015-08-21 21:14:02 -04:00
|
|
|
|
{
|
2017-11-16 18:09:19 -05:00
|
|
|
|
public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response)
|
2015-08-21 21:14:02 -04:00
|
|
|
|
{
|
2018-02-15 23:01:28 -05:00
|
|
|
|
#if DEBUG
|
2017-11-14 16:36:55 -05:00
|
|
|
|
var logger = ApplicationManager.GetInstance().GetLogger();
|
2017-11-16 18:09:19 -05:00
|
|
|
|
logger.WriteDebug($"HTTP request {request.Path}");
|
|
|
|
|
logger.WriteDebug($"QueryString: {request.QueryString}");
|
|
|
|
|
logger.WriteDebug($"IP: {request.IPAddress}");
|
2018-02-15 23:01:28 -05:00
|
|
|
|
#endif
|
2017-11-14 16:36:55 -05:00
|
|
|
|
|
2017-05-26 18:49:27 -04:00
|
|
|
|
NameValueCollection querySet = new NameValueCollection();
|
2017-05-27 00:22:50 -04:00
|
|
|
|
|
2017-05-26 18:49:27 -04:00
|
|
|
|
if (request.QueryString != null)
|
2017-11-16 18:09:19 -05:00
|
|
|
|
querySet = System.Web.HttpUtility.ParseQueryString(request.QueryString);
|
2017-05-26 18:49:27 -04:00
|
|
|
|
|
2017-11-16 18:09:19 -05:00
|
|
|
|
querySet.Set("IP", request.IPAddress);
|
2017-05-26 18:49:27 -04:00
|
|
|
|
|
2017-08-17 19:28:08 -04:00
|
|
|
|
try
|
2017-05-27 00:22:50 -04:00
|
|
|
|
{
|
2017-11-18 01:59:37 -05:00
|
|
|
|
request.Path = String.IsNullOrEmpty(request.Path) ? "/" : request.Path;
|
2017-08-17 19:28:08 -04:00
|
|
|
|
SharedLibrary.HttpResponse requestedPage = WebService.GetPage(request.Path, querySet, request.Headers);
|
|
|
|
|
|
2017-10-03 19:17:35 -04:00
|
|
|
|
bool binaryContent = requestedPage.BinaryContent != null;
|
|
|
|
|
if (requestedPage.content != null && requestedPage.content.GetType() != typeof(string))
|
2018-02-14 14:01:26 -05:00
|
|
|
|
#if !DEBUG
|
2017-10-03 19:17:35 -04:00
|
|
|
|
requestedPage.content = Newtonsoft.Json.JsonConvert.SerializeObject(requestedPage.content);
|
2018-02-14 14:01:26 -05:00
|
|
|
|
#else
|
|
|
|
|
requestedPage.content = Newtonsoft.Json.JsonConvert.SerializeObject(requestedPage.content, Newtonsoft.Json.Formatting.Indented);
|
|
|
|
|
#endif
|
2017-10-03 19:17:35 -04:00
|
|
|
|
|
2018-02-16 23:24:03 -05:00
|
|
|
|
string maxAge = requestedPage.contentType == "application/json" ? "0" : "21600";
|
2017-08-17 19:28:08 -04:00
|
|
|
|
var headers = new HttpResponseHead()
|
|
|
|
|
{
|
|
|
|
|
Status = "200 OK",
|
|
|
|
|
Headers = new Dictionary<string, string>()
|
2015-08-21 21:14:02 -04:00
|
|
|
|
{
|
2017-05-26 18:49:27 -04:00
|
|
|
|
{ "Content-Type", requestedPage.contentType },
|
2017-10-03 19:17:35 -04:00
|
|
|
|
{ "Content-Length", binaryContent ? requestedPage.BinaryContent.Length.ToString() : requestedPage.content.ToString().Length.ToString() },
|
2017-05-26 18:49:27 -04:00
|
|
|
|
{ "Access-Control-Allow-Origin", "*" },
|
2017-10-04 19:01:04 -04:00
|
|
|
|
{ "Cache-Control", $"public,max-age={maxAge}"}
|
2015-08-21 21:14:02 -04:00
|
|
|
|
}
|
2017-08-17 19:28:08 -04:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
foreach (var key in requestedPage.additionalHeaders.Keys)
|
|
|
|
|
headers.Headers.Add(key, requestedPage.additionalHeaders[key]);
|
2017-10-03 19:17:35 -04:00
|
|
|
|
if (!binaryContent)
|
|
|
|
|
response.OnResponse(headers, new BufferedProducer((string)requestedPage.content));
|
|
|
|
|
else
|
|
|
|
|
response.OnResponse(headers, new BufferedProducer(requestedPage.BinaryContent));
|
2017-08-17 19:28:08 -04:00
|
|
|
|
}
|
2017-05-26 18:49:27 -04:00
|
|
|
|
|
2017-08-17 19:28:08 -04:00
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2017-11-13 16:58:23 -05:00
|
|
|
|
if (e.GetType() == typeof(FormatException))
|
|
|
|
|
{
|
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteWarning("Request parameter data format was incorrect");
|
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteDebug($"Request Path {request.Path}");
|
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteDebug($"Request Query String {request.QueryString}");
|
|
|
|
|
response.OnResponse(new HttpResponseHead()
|
|
|
|
|
{
|
|
|
|
|
Status = "400 Bad Request",
|
|
|
|
|
Headers = new Dictionary<string, string>()
|
|
|
|
|
{
|
|
|
|
|
{ "Content-Type", "text/html" },
|
|
|
|
|
{ "Content-Length", "0"},
|
|
|
|
|
}
|
|
|
|
|
}, new BufferedProducer(""));
|
|
|
|
|
}
|
2017-09-27 16:07:43 -04:00
|
|
|
|
|
2017-11-13 16:58:23 -05:00
|
|
|
|
else
|
2017-08-17 19:28:08 -04:00
|
|
|
|
{
|
2017-11-13 16:58:23 -05:00
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteError($"Webfront error during request");
|
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteDebug($"Message: {e.Message}");
|
|
|
|
|
ApplicationManager.GetInstance().Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
|
|
|
|
|
|
|
|
|
|
response.OnResponse(new HttpResponseHead()
|
|
|
|
|
{
|
|
|
|
|
Status = "500 Internal Server Error",
|
|
|
|
|
Headers = new Dictionary<string, string>()
|
2017-08-17 19:28:08 -04:00
|
|
|
|
{
|
|
|
|
|
{ "Content-Type", "text/html" },
|
|
|
|
|
{ "Content-Length", "0"},
|
|
|
|
|
}
|
2017-11-13 16:58:23 -05:00
|
|
|
|
}, new BufferedProducer(""));
|
|
|
|
|
}
|
2017-08-17 19:28:08 -04:00
|
|
|
|
}
|
2015-08-21 21:14:02 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class BufferedProducer : IDataProducer
|
|
|
|
|
{
|
|
|
|
|
ArraySegment<byte> data;
|
|
|
|
|
|
2017-11-13 16:58:23 -05:00
|
|
|
|
public BufferedProducer(string data) : this(data, Encoding.ASCII) { }
|
2015-08-21 21:14:02 -04:00
|
|
|
|
public BufferedProducer(string data, Encoding encoding) : this(encoding.GetBytes(data)) { }
|
|
|
|
|
public BufferedProducer(byte[] data) : this(new ArraySegment<byte>(data)) { }
|
2017-05-26 18:49:27 -04:00
|
|
|
|
|
2015-08-21 21:14:02 -04:00
|
|
|
|
public BufferedProducer(ArraySegment<byte> data)
|
|
|
|
|
{
|
|
|
|
|
this.data = data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IDisposable Connect(IDataConsumer channel)
|
|
|
|
|
{
|
2017-11-13 16:58:23 -05:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
channel?.OnData(data, null);
|
|
|
|
|
channel?.OnEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (Exception)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-21 21:14:02 -04:00
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class BufferedConsumer : IDataConsumer
|
|
|
|
|
{
|
|
|
|
|
List<ArraySegment<byte>> buffer = new List<ArraySegment<byte>>();
|
|
|
|
|
Action<string> resultCallback;
|
|
|
|
|
Action<Exception> errorCallback;
|
|
|
|
|
|
|
|
|
|
public BufferedConsumer(Action<string> resultCallback, Action<Exception> errorCallback)
|
|
|
|
|
{
|
|
|
|
|
this.resultCallback = resultCallback;
|
|
|
|
|
this.errorCallback = errorCallback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool OnData(ArraySegment<byte> data, Action continuation)
|
|
|
|
|
{
|
2017-11-13 16:58:23 -05:00
|
|
|
|
// this should hopefully clean the non ascii characters out.
|
|
|
|
|
buffer?.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(Encoding.ASCII.GetString(data.ToArray()))));
|
2015-08-21 21:14:02 -04:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnError(Exception error)
|
|
|
|
|
{
|
2017-11-13 16:58:23 -05:00
|
|
|
|
// errorCallback?.Invoke(error);
|
2015-08-21 21:14:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnEnd()
|
|
|
|
|
{
|
|
|
|
|
var str = buffer
|
2017-11-13 16:58:23 -05:00
|
|
|
|
.Select(b => Encoding.ASCII.GetString(b.Array, b.Offset, b.Count))
|
2015-08-21 21:14:02 -04:00
|
|
|
|
.Aggregate((result, next) => result + next);
|
|
|
|
|
|
|
|
|
|
resultCallback(str);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-26 18:49:27 -04:00
|
|
|
|
}
|