ln.http/ln.http/router/SimpleRouter.cs

114 lines
4.5 KiB
C#

using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace ln.http.router
{
public delegate bool RouterFilterDelegate(SimpleRouter sender, ref HttpRoutingContext routingContext, HttpRequest httpRequest, out HttpResponse httpResponse);
public class SimpleRouter : IHttpRouter
{
public event RouterFilterDelegate OnRoute;
List<SimpleRoute> routes = new List<SimpleRoute>();
public SimpleRoute[] Routes => routes.ToArray();
public SimpleRouter()
{
}
public void AddSimpleRoute(string simpleRoute, Func<HttpRoutingContext, HttpRequest, HttpResponse> target) => AddSimpleRoute(simpleRoute, new RouterTarget(target));
public void AddSimpleRoute(string simpleRoute, Func<string, HttpRequest, HttpResponse> target) => AddSimpleRoute(simpleRoute, new RouterTarget(target));
public void AddSimpleRoute(string simpleRoute, Func<HttpRequest, HttpResponse> target) => AddSimpleRoute(simpleRoute, new RouterTarget(target));
public void AddSimpleRoute(string simpleRoute, IHttpRouter target) => AddSimpleRoute(simpleRoute, target, simpleRoute.Split('/').Length);
public void AddSimpleRoute(string simpleRoute, IHttpRouter target, int priority)
{
string[] parts = simpleRoute.Split(new char[] { '/' });
string[] reparts = parts.Select((part) =>
{
if (part.StartsWith(":", StringComparison.InvariantCulture))
if (part.EndsWith("*", StringComparison.InvariantCulture))
return string.Format("(?<{0}>[^/]+)(?<_>/.*)?", part.Substring(1, part.Length - 2));
else
return string.Format("(?<{0}>[^/]+)", part.Substring(1));
else if (part.Equals("*"))
return string.Format("(?<_>.*)");
else
return string.Format("{0}", part);
}).ToArray();
string reroute = string.Format("{0}\\/?$", string.Join("/", reparts));
AddRoute(reroute, target, priority);
}
public void AddRoute(String route, IHttpRouter target) => AddRoute(route, target, 0);
public void AddRoute(String route, IHttpRouter target,int priority)
{
lock (this)
{
routes.Add(new SimpleRoute(route, target, priority));
routes.Sort((SimpleRoute a, SimpleRoute b) => b.Priority - a.Priority);
}
}
public void Remove(SimpleRoute simpleRoute) => routes.Remove(simpleRoute);
public HttpResponse Route(HttpRoutingContext routingContext, HttpRequest httpRequest)
{
HttpResponse httpResponse;
if (OnRoute != null)
{
foreach (RouterFilterDelegate filterDelegate in OnRoute.GetInvocationList())
{
if (filterDelegate(this, ref routingContext, httpRequest, out httpResponse))
return httpResponse;
}
}
foreach (SimpleRoute simpleRoute in routes.ToArray())
{
Match match = simpleRoute.Route.Match(routingContext.Path);
if (match.Success)
{
string residual = "";
foreach (Group group in match.Groups)
{
httpRequest?.SetParameter(group.Name, group.Value);
if (group.Name.Equals("_"))
if (group.Value.StartsWith("/", StringComparison.InvariantCulture))
residual = group.Value;
else
residual = "/" + group.Value;
}
httpResponse = simpleRoute.Target.Route(routingContext.Routed(residual), httpRequest);
if (httpResponse != null)
return httpResponse;
}
}
return null;
}
public class SimpleRoute
{
public int Priority { get; }
public Regex Route { get; }
public IHttpRouter Target { get; }
public SimpleRoute(string regex, IHttpRouter target) : this(regex, target, 0) { }
public SimpleRoute(string regex, IHttpRouter target,int priority)
{
Route = new Regex(regex);
Target = target;
Priority = priority;
}
}
}
}