diff --git a/Rest.Net.Example/Program.cs b/Rest.Net.Example/Program.cs
index aecad43..c478bef 100644
--- a/Rest.Net.Example/Program.cs
+++ b/Rest.Net.Example/Program.cs
@@ -34,29 +34,44 @@ namespace MontoyaTech.Rest.Net.Example
new Route(HttpRequestMethod.Get, "/json", Json)
);
+ listener.RequestPreProcessEvent += (ListenerContext context) => {
+ Console.WriteLine("Request start: " + context.Request.RawUrl);
+ return true;
+ };
+
+ listener.RequestPostProcessEvent += (ListenerContext context) =>
+ {
+ Console.WriteLine("Request end: " + context.Request.RawUrl);
+ };
+
listener.Start();
+ Console.WriteLine("Available routes:");
+
+ foreach (var route in listener.Routes)
+ Console.WriteLine($"- [{route.Method}] {route.Syntax}");
+
Console.WriteLine($"Rest api server running at http://localhost:{listener.Port}");
listener.Block();
}
- public static HttpListenerResponse Status(RouteContext context)
+ public static HttpListenerResponse Status(ListenerContext context)
{
return context.Response.WithStatus(HttpStatusCode.OK).WithText("Everything is operational. 👍");
}
- public static HttpListenerResponse Add(RouteContext context, double a, double b)
+ public static HttpListenerResponse Add(ListenerContext context, double a, double b)
{
return context.Response.WithStatus(HttpStatusCode.OK).WithText((a + b).ToString());
}
- public static HttpListenerResponse Signup(RouteContext context, User user)
+ public static HttpListenerResponse Signup(ListenerContext context, User user)
{
return context.Response.WithStatus(HttpStatusCode.OK).WithText("User:" + user.Name);
}
- public static HttpListenerResponse Json(RouteContext context)
+ public static HttpListenerResponse Json(ListenerContext context)
{
return context.Response.WithStatus(HttpStatusCode.OK).WithJson(new User("Rest.Net"));
}
diff --git a/Rest.Net/RoutePostprocess.cs b/Rest.Net/Events/RequestPostProcessEventHandler.cs
similarity index 51%
rename from Rest.Net/RoutePostprocess.cs
rename to Rest.Net/Events/RequestPostProcessEventHandler.cs
index 25d7b15..69d1814 100644
--- a/Rest.Net/RoutePostprocess.cs
+++ b/Rest.Net/Events/RequestPostProcessEventHandler.cs
@@ -4,11 +4,11 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace MontoyaTech.Rest.Net
+namespace MontoyaTech.Rest.Net.Events
{
///
- /// A route post process delegate that can be used to process the response from routes.
+ /// A delegate to post process requests.
///
///
- public delegate void RoutePostprocess(RouteContext context);
+ public delegate void RequestPostProcessEventHandler(ListenerContext context);
}
diff --git a/Rest.Net/Events/RequestPreProcessEventHandler.cs b/Rest.Net/Events/RequestPreProcessEventHandler.cs
new file mode 100644
index 0000000..0c24b76
--- /dev/null
+++ b/Rest.Net/Events/RequestPreProcessEventHandler.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MontoyaTech.Rest.Net.Events
+{
+ ///
+ /// A delegate that can be used to pre process requests and stop them from being handled by routes if needed.
+ ///
+ ///
+ ///
+ public delegate bool RequestPreProcessEventHandler(ListenerContext context);
+}
diff --git a/Rest.Net/Events/RouteExceptionEventHandler.cs b/Rest.Net/Events/RouteExceptionEventHandler.cs
new file mode 100644
index 0000000..fb6ea31
--- /dev/null
+++ b/Rest.Net/Events/RouteExceptionEventHandler.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MontoyaTech.Rest.Net.Events
+{
+ ///
+ /// A delegate that can be used to handle route exceptions.
+ ///
+ ///
+ ///
+ ///
+ public delegate void RouteExceptionEventHandler(Route route, ListenerContext context, Exception ex);
+}
diff --git a/Rest.Net/RouteContext.cs b/Rest.Net/ListenerContext.cs
similarity index 71%
rename from Rest.Net/RouteContext.cs
rename to Rest.Net/ListenerContext.cs
index c1eb3ef..98cca61 100644
--- a/Rest.Net/RouteContext.cs
+++ b/Rest.Net/ListenerContext.cs
@@ -8,10 +8,10 @@ using System.Net;
namespace MontoyaTech.Rest.Net
{
///
- /// An outline of a Route Context which includes
- /// the request and response for a route.
+ /// An outline of a Listener Context which includes
+ /// the given request and a resposne.
///
- public class RouteContext
+ public class ListenerContext
{
///
/// The Http Request that requested this route.
@@ -24,11 +24,11 @@ namespace MontoyaTech.Rest.Net
public HttpListenerResponse Response = null;
///
- /// Creates a new RouteContext with a given request and response.
+ /// Creates a new ListenerContext with a given request and response.
///
///
///
- public RouteContext(HttpListenerRequest request, HttpListenerResponse response)
+ public ListenerContext(HttpListenerRequest request, HttpListenerResponse response)
{
this.Request = request;
this.Response = response;
diff --git a/Rest.Net/Rest.Net.csproj b/Rest.Net/Rest.Net.csproj
index 3e554d8..5b0cfcd 100644
--- a/Rest.Net/Rest.Net.csproj
+++ b/Rest.Net/Rest.Net.csproj
@@ -8,7 +8,7 @@
True
MontoyaTech
MontoyaTech
- MontoyaTech 2022
+ MontoyaTech 2023
https://code.montoyatech.com/MontoyaTech/Rest.Net
A simple C# library for creating a rest api.
MontoyaTech;Rest.Net
@@ -17,7 +17,7 @@
MontoyaTech.Rest.Net
MontoyaTech.Rest.Net
True
- 1.1.1
+ 1.1.2
HttpListener now returns NotFound if no route was found. Added WithRedirect and WithHtml extensions.
diff --git a/Rest.Net/Route.cs b/Rest.Net/Route.cs
index 83cdeac..f654322 100644
--- a/Rest.Net/Route.cs
+++ b/Rest.Net/Route.cs
@@ -25,7 +25,7 @@ namespace MontoyaTech.Rest.Net
///
/// The target function to invoke if this route is invoked.
///
- private Func Target;
+ private Func Target;
///
/// Whether or not to close the response after the route is invoked.
@@ -42,7 +42,7 @@ namespace MontoyaTech.Rest.Net
///
///
///
- public Route(string method, string syntax, Func target, bool closeResponse = true)
+ public Route(string method, string syntax, Func target, bool closeResponse = true)
{
this.Method = method;
this.Syntax = syntax;
@@ -58,7 +58,7 @@ namespace MontoyaTech.Rest.Net
///
///
///
- public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
+ public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
: this(method.ToString(), syntax, target, closeResponse) { }
///
@@ -110,7 +110,7 @@ namespace MontoyaTech.Rest.Net
///
///
///
- public virtual void Invoke(RouteContext context, params string[] arguments)
+ public virtual void Invoke(ListenerContext context, params string[] arguments)
{
this.Target.Invoke(context);
}
@@ -118,9 +118,9 @@ namespace MontoyaTech.Rest.Net
public class Route : Route
{
- private Func Target;
+ private Func Target;
- public Route(string method, string syntax, Func target, bool closeResponse = true)
+ public Route(string method, string syntax, Func target, bool closeResponse = true)
{
this.Method = method;
this.Syntax = syntax;
@@ -128,10 +128,10 @@ namespace MontoyaTech.Rest.Net
this.CloseResponse = closeResponse;
}
- public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
+ public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
: this(method.ToString(), syntax, target, closeResponse) { }
- public override void Invoke(RouteContext context, params string[] arguments)
+ public override void Invoke(ListenerContext context, params string[] arguments)
{
this.Target.DynamicInvoke(context, RouteArgumentConverter.Convert(arguments[0]));
}
@@ -139,9 +139,9 @@ namespace MontoyaTech.Rest.Net
public class Route : Route
{
- private Func Target;
+ private Func Target;
- public Route(string method, string syntax, Func target, bool closeResponse = true)
+ public Route(string method, string syntax, Func target, bool closeResponse = true)
{
this.Method = method;
this.Syntax = syntax;
@@ -149,10 +149,10 @@ namespace MontoyaTech.Rest.Net
this.CloseResponse = closeResponse;
}
- public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
+ public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
: this(method.ToString(), syntax, target, closeResponse) { }
- public override void Invoke(RouteContext context, params string[] arguments)
+ public override void Invoke(ListenerContext context, params string[] arguments)
{
this.Target.DynamicInvoke(
context,
@@ -164,9 +164,9 @@ namespace MontoyaTech.Rest.Net
public class Route : Route
{
- private Func Target;
+ private Func Target;
- public Route(string method, string syntax, Func target, bool closeResponse = true)
+ public Route(string method, string syntax, Func target, bool closeResponse = true)
{
this.Method = method;
this.Syntax = syntax;
@@ -174,10 +174,10 @@ namespace MontoyaTech.Rest.Net
this.CloseResponse = closeResponse;
}
- public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
+ public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
: this(method.ToString(), syntax, target, closeResponse) { }
- public override void Invoke(RouteContext context, params string[] arguments)
+ public override void Invoke(ListenerContext context, params string[] arguments)
{
this.Target.DynamicInvoke(
context,
@@ -190,9 +190,9 @@ namespace MontoyaTech.Rest.Net
public class Route : Route
{
- private Func Target;
+ private Func Target;
- public Route(string method, string syntax, Func target, bool closeResponse = true)
+ public Route(string method, string syntax, Func target, bool closeResponse = true)
{
this.Method = method;
this.Syntax = syntax;
@@ -200,10 +200,10 @@ namespace MontoyaTech.Rest.Net
this.CloseResponse = closeResponse;
}
- public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
+ public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
: this(method.ToString(), syntax, target, closeResponse) { }
- public override void Invoke(RouteContext context, params string[] arguments)
+ public override void Invoke(ListenerContext context, params string[] arguments)
{
this.Target.DynamicInvoke(
context,
@@ -217,9 +217,9 @@ namespace MontoyaTech.Rest.Net
public class Route : Route
{
- private Func Target;
+ private Func Target;
- public Route(string method, string syntax, Func target, bool closeResponse = true)
+ public Route(string method, string syntax, Func target, bool closeResponse = true)
{
this.Method = method;
this.Syntax = syntax;
@@ -227,10 +227,10 @@ namespace MontoyaTech.Rest.Net
this.CloseResponse = closeResponse;
}
- public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
+ public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
: this(method.ToString(), syntax, target, closeResponse) { }
- public override void Invoke(RouteContext context, params string[] arguments)
+ public override void Invoke(ListenerContext context, params string[] arguments)
{
this.Target.DynamicInvoke(
context,
@@ -245,9 +245,9 @@ namespace MontoyaTech.Rest.Net
public class Route : Route
{
- private Func Target;
+ private Func Target;
- public Route(string method, string syntax, Func target, bool closeResponse = true)
+ public Route(string method, string syntax, Func target, bool closeResponse = true)
{
this.Method = method;
this.Syntax = syntax;
@@ -255,10 +255,10 @@ namespace MontoyaTech.Rest.Net
this.CloseResponse = closeResponse;
}
- public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
+ public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
: this(method.ToString(), syntax, target, closeResponse) { }
- public override void Invoke(RouteContext context, params string[] arguments)
+ public override void Invoke(ListenerContext context, params string[] arguments)
{
this.Target.DynamicInvoke(
context,
@@ -274,9 +274,9 @@ namespace MontoyaTech.Rest.Net
public class Route : Route
{
- private Func Target;
+ private Func Target;
- public Route(string method, string syntax, Func target, bool closeResponse = true)
+ public Route(string method, string syntax, Func target, bool closeResponse = true)
{
this.Method = method;
this.Syntax = syntax;
@@ -284,10 +284,10 @@ namespace MontoyaTech.Rest.Net
this.CloseResponse = closeResponse;
}
- public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
+ public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
: this(method.ToString(), syntax, target, closeResponse) { }
- public override void Invoke(RouteContext context, params string[] arguments)
+ public override void Invoke(ListenerContext context, params string[] arguments)
{
this.Target.DynamicInvoke(
context,
@@ -304,9 +304,9 @@ namespace MontoyaTech.Rest.Net
public class Route : Route
{
- private Func Target;
+ private Func Target;
- public Route(string method, string syntax, Func target, bool closeResponse = true)
+ public Route(string method, string syntax, Func target, bool closeResponse = true)
{
this.Method = method;
this.Syntax = syntax;
@@ -314,10 +314,10 @@ namespace MontoyaTech.Rest.Net
this.CloseResponse = closeResponse;
}
- public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
+ public Route(HttpRequestMethod method, string syntax, Func target, bool closeResponse = true)
: this(method.ToString(), syntax, target, closeResponse) { }
- public override void Invoke(RouteContext context, params string[] arguments)
+ public override void Invoke(ListenerContext context, params string[] arguments)
{
this.Target.DynamicInvoke(
context,
diff --git a/Rest.Net/RouteListener.cs b/Rest.Net/RouteListener.cs
index 0c50ba2..cf4b7c0 100644
--- a/Rest.Net/RouteListener.cs
+++ b/Rest.Net/RouteListener.cs
@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Threading;
+using MontoyaTech.Rest.Net.Events;
namespace MontoyaTech.Rest.Net
{
@@ -32,12 +33,17 @@ namespace MontoyaTech.Rest.Net
///
/// An event to preprocess routes before the route is executed.
///
- public event RoutePreprocess PreprocessEvent;
+ public event RequestPreProcessEventHandler RequestPreProcessEvent;
///
/// An event to postprocess routes before the route response is returned.
///
- public event RoutePostprocess PostprocessEvent;
+ public event RequestPostProcessEventHandler RequestPostProcessEvent;
+
+ ///
+ /// An event that is invoked when a route has an unhandled exception.
+ ///
+ public event RouteExceptionEventHandler RouteExceptionEvent;
///
/// Creates a new RouteListener with the default port number.
@@ -116,12 +122,12 @@ namespace MontoyaTech.Rest.Net
bool close = true;
string[] arguments = null;
- var context = new RouteContext(ctx.Request, ctx.Response);
+ var context = new ListenerContext(ctx.Request, ctx.Response);
//Preprocess the route context, if it returns false, then we have to not invoke the route.
try
{
- if (this.PreprocessEvent != null && !this.PreprocessEvent.Invoke(context))
+ if (this.RequestPreProcessEvent != null && !this.RequestPreProcessEvent.Invoke(context))
handled = true;
}
catch { }
@@ -138,8 +144,11 @@ namespace MontoyaTech.Rest.Net
{
this.Routes[i].Invoke(context, arguments);
}
- catch
+ catch (Exception ex)
{
+ if (this.RouteExceptionEvent != null)
+ this.RouteExceptionEvent.Invoke(this.Routes[i], context, ex);
+
ctx.Response.WithStatus(HttpStatusCode.InternalServerError);
}
@@ -150,8 +159,8 @@ namespace MontoyaTech.Rest.Net
//Post process the route context.
try
{
- if (this.PostprocessEvent != null)
- this.PostprocessEvent.Invoke(context);
+ if (this.RequestPostProcessEvent != null)
+ this.RequestPostProcessEvent.Invoke(context);
}
catch { }
diff --git a/Rest.Net/RoutePreprocess.cs b/Rest.Net/RoutePreprocess.cs
deleted file mode 100644
index eeb517f..0000000
--- a/Rest.Net/RoutePreprocess.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MontoyaTech.Rest.Net
-{
- ///
- /// A route preprocess delegate that can be used to process requests before they reach a route
- /// and reject them if needed.
- ///
- ///
- ///
- public delegate bool RoutePreprocess(RouteContext context);
-}