diff --git a/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj b/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj
index 932b4ab..63ceba2 100644
--- a/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj
+++ b/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj
@@ -9,7 +9,7 @@
Esiur Entity Framework Extension
true
Esiur.Stores.EntityCore
- 1.2.9
+ 1.3.0
latest
diff --git a/Esiur.Stores.MongoDB/Esiur.Stores.MongoDB.csproj b/Esiur.Stores.MongoDB/Esiur.Stores.MongoDB.csproj
index 082f478..82dd06d 100644
--- a/Esiur.Stores.MongoDB/Esiur.Stores.MongoDB.csproj
+++ b/Esiur.Stores.MongoDB/Esiur.Stores.MongoDB.csproj
@@ -11,7 +11,7 @@
http://www.esiur.com
https://github.com/esiur/esiur-dotnet/
True
- 1.5.4
+ 1.5.5
Esiur.Stores.MongoDB
latest
diff --git a/Esiur/Data/Codec.cs b/Esiur/Data/Codec.cs
index bb6e708..bcba455 100644
--- a/Esiur/Data/Codec.cs
+++ b/Esiur/Data/Codec.cs
@@ -307,6 +307,9 @@ public static class Codec
else if (genericType == typeof(ValueTuple<,>)
|| genericType == typeof(ValueTuple<,,>)
|| genericType == typeof(ValueTuple<,,,>)
+ || genericType == typeof(ValueTuple<,,,,>)
+ || genericType == typeof(ValueTuple<,,,,,>)
+ || genericType == typeof(ValueTuple<,,,,,,>)
)
{
var (hdr, data) = DataSerializer.TupleComposer(valueOrSource, connection);
diff --git a/Esiur/Esiur.csproj b/Esiur/Esiur.csproj
index 09e175c..dd27022 100644
--- a/Esiur/Esiur.csproj
+++ b/Esiur/Esiur.csproj
@@ -6,7 +6,7 @@
Ahmed Kh. Zamil
http://www.esiur.com
true
- 2.1.1
+ 2.2.1
https://github.com/esiur/esiur-dotnet
Ahmed Kh. Zamil
diff --git a/Esiur/Net/HTTP/HTTPServer.cs b/Esiur/Net/HTTP/HTTPServer.cs
index 9444d43..d26df7f 100644
--- a/Esiur/Net/HTTP/HTTPServer.cs
+++ b/Esiur/Net/HTTP/HTTPServer.cs
@@ -38,6 +38,9 @@ using Esiur.Core;
using Esiur.Net.Packets;
using System.Security.Cryptography.X509Certificates;
using Esiur.Resource;
+using System.Text.RegularExpressions;
+using System.Linq;
+using System.Reflection;
namespace Esiur.Net.HTTP;
public class HTTPServer : NetworkServer, IResource
@@ -45,6 +48,128 @@ public class HTTPServer : NetworkServer, IResource
Dictionary sessions = new Dictionary();
HTTPFilter[] filters = new HTTPFilter[0];
+ Dictionary> routes = new()
+ {
+ [HTTPRequestPacket.HTTPMethod.GET] = new List(),
+ [HTTPRequestPacket.HTTPMethod.POST] = new List(),
+ [HTTPRequestPacket.HTTPMethod.HEAD] = new List(),
+ [HTTPRequestPacket.HTTPMethod.OPTIONS] = new List(),
+ [HTTPRequestPacket.HTTPMethod.UNKNOWN] = new List(),
+ [HTTPRequestPacket.HTTPMethod.DELETE] = new List(),
+ [HTTPRequestPacket.HTTPMethod.TRACE] = new List(),
+ [HTTPRequestPacket.HTTPMethod.CONNECT] = new List(),
+ [HTTPRequestPacket.HTTPMethod.PUT] = new List()
+ };
+
+ //List GetRoutes = new List();
+ //List PostRoutes = new List();
+
+
+ class RouteInfo
+ {
+ public Delegate Handler;
+ public Regex Pattern;
+ Dictionary ParameterIndex = new();
+ int? SenderIndex;
+ //bool HasSender;
+ int ArgumentsCount;
+
+ public RouteInfo(Delegate handler, Regex pattern)
+ {
+
+ Pattern = pattern;
+ Handler = handler;
+
+ var ps = handler.Method.GetParameters();
+
+ ArgumentsCount = ps.Length;
+
+ var last = ps.LastOrDefault();
+
+ if (last != null && last.ParameterType == typeof(HTTPConnection))
+ {
+
+ SenderIndex = ps.Length - 1;
+ for (var i = 0; i < ps.Length - 1; i++)
+ ParameterIndex[ps[i].Name] = ps[i];
+ }
+ else
+ {
+ for (var i = 0; i < ps.Length; i++)
+ ParameterIndex[ps[i].Name] = ps[i];
+ }
+ }
+
+
+ public bool Invoke(HTTPConnection sender)
+ {
+ var match = Pattern.Match(sender.Request.URL);
+
+ if (!match.Success)
+ return false;
+
+ var args = new object[ArgumentsCount];
+
+ foreach (var kv in ParameterIndex)
+ {
+ var g = match.Groups[kv.Key];
+ args[kv.Value.Position] = DC.CastConvert(g.Value, kv.Value.ParameterType);
+ }
+
+ if (SenderIndex != null)
+ args[(int)SenderIndex] = sender;
+
+ var rt = Handler.DynamicInvoke(args);
+
+ if (rt is bool)
+ return (bool)rt;
+
+ return true;
+ }
+ }
+
+ struct VarInfo
+ {
+ public string Pre;
+ public string Post;
+ public string VarName;
+
+ public string Build()
+ {
+ return Regex.Escape(Pre) + @"(?<" + VarName + @">[^\{]*)" + Regex.Escape(Post);
+ }
+ }
+
+
+
+ static Regex getRouteRegex(string url)
+ {
+ var sc = Regex.Match(url, @"([^\{]*)\{([^\}]*)\}([^\{]*)");
+
+ List vars = new List();
+
+ while (sc.Success)
+ {
+ vars.Add(new VarInfo()
+ {
+ Pre = sc.Groups[1].Value,
+ VarName = sc.Groups[2].Value,
+ Post = sc.Groups[3].Value
+ });
+ sc = sc.NextMatch();
+ }
+
+ if (vars.Count > 0)
+ {
+ return new Regex("^" + String.Join("", vars.Select(x => x.Build()).ToArray()) + "$");
+ }
+ else
+ {
+ return new Regex("^" + Regex.Escape(url) + "$");
+ }
+ }
+
+
public Instance Instance
{
get;
@@ -149,9 +274,19 @@ public class HTTPServer : NetworkServer, IResource
internal bool Execute(HTTPConnection sender)
{
+ foreach (var route in routes[sender.Request.Method])
+ {
+ if (route.Invoke(sender))
+ return true;
+ }
+
+
foreach (var resource in filters)
if (resource.Execute(sender).Wait(30000))
return true;
+
+
+
return false;
}
@@ -159,9 +294,17 @@ public class HTTPServer : NetworkServer, IResource
public void MapGet(string pattern, Delegate handler)
{
- // if (p)
+ var regex = getRouteRegex(pattern);
+ var list = routes[HTTPRequestPacket.HTTPMethod.GET];
+ list.Add(new RouteInfo(handler, regex));
}
+ public void MapPost(string pattern, Delegate handler)
+ {
+ var regex = getRouteRegex(pattern);
+ var list = routes[HTTPRequestPacket.HTTPMethod.POST];
+ list.Add(new RouteInfo(handler, regex));
+ }
/*
protected override void SessionEnded(NetworkSession session)
@@ -260,11 +403,11 @@ public class HTTPServer : NetworkServer, IResource
protected override void ClientConnected(HTTPConnection connection)
{
- if (filters.Length == 0)
- {
- connection.Close();
- return;
- }
+ //if (filters.Length == 0 && routes.)
+ //{
+ // connection.Close();
+ // return;
+ //}
foreach (var resource in filters)
{
diff --git a/Esiur/Net/IIP/DistributedConnection.cs b/Esiur/Net/IIP/DistributedConnection.cs
index f8bf7f1..396e8c9 100644
--- a/Esiur/Net/IIP/DistributedConnection.cs
+++ b/Esiur/Net/IIP/DistributedConnection.cs
@@ -357,7 +357,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
if (ready)
{
var rt = packet.Parse(msg, offset, ends);
- Console.WriteLine("Rec: " + chunkId + " " + packet.ToString());
+ //Console.WriteLine("Rec: " + chunkId + " " + packet.ToString());
/*
if (packet.Command == IIPPacketCommand.Event)
@@ -696,7 +696,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
}
}
- Console.WriteLine(msg.GetString(offset, ends - offset));
+ //Console.WriteLine(msg.GetString(offset, ends - offset));
var rt = authPacket.Parse(msg, offset, ends);
diff --git a/Esiur/Net/NetworkServer.cs b/Esiur/Net/NetworkServer.cs
index a0fb3b1..5367822 100644
--- a/Esiur/Net/NetworkServer.cs
+++ b/Esiur/Net/NetworkServer.cs
@@ -121,7 +121,7 @@ public abstract class NetworkServer : IDestructible where TConnecti
return;
}
- Console.WriteLine("New Socket ... " + DateTime.Now);
+ //Console.WriteLine("New Socket ... " + DateTime.Now);
var c = new TConnection();
//c.OnClose += ClientDisconnectedEventReceiver;
diff --git a/Esiur/Net/Sockets/TCPSocket.cs b/Esiur/Net/Sockets/TCPSocket.cs
index 41afcf1..9cfa15a 100644
--- a/Esiur/Net/Sockets/TCPSocket.cs
+++ b/Esiur/Net/Sockets/TCPSocket.cs
@@ -79,6 +79,10 @@ public class TCPSocket : ISocket
public bool Begin()
{
+ // Socket destroyed
+ if (receiveBuffer == null)
+ return false;
+
if (began)
return false;
@@ -539,8 +543,7 @@ public class TCPSocket : ISocket
public void Destroy()
{
- Global.Counters["Sck_D_1"]++;
-
+
Close();
receiveNetworkBuffer = null;
@@ -557,8 +560,7 @@ public class TCPSocket : ISocket
OnDestroy?.Invoke(this);
OnDestroy = null;
- Global.Counters["Sck_D_2"]++;
- }
+ }
public ISocket Accept()
{
diff --git a/Esiur/Resource/Template/TypeTemplate.cs b/Esiur/Resource/Template/TypeTemplate.cs
index d4bfaa2..22b4405 100644
--- a/Esiur/Resource/Template/TypeTemplate.cs
+++ b/Esiur/Resource/Template/TypeTemplate.cs
@@ -752,8 +752,6 @@ public class TypeTemplate
od.className = data.GetString(offset + 1, data[offset]);
offset += (uint)data[offset] + 1;
- if (od.className == "Test.MyChildRecord")
- Console.WriteLine();
if (hasParent)
{
diff --git a/Test/Program.cs b/Test/Program.cs
index 33c068e..3ec926b 100644
--- a/Test/Program.cs
+++ b/Test/Program.cs
@@ -40,6 +40,8 @@ using Esiur.Resource.Template;
using System.Collections;
using System.Runtime.CompilerServices;
using Esiur.Proxy;
+using System.Text.RegularExpressions;
+using System.Collections.Generic;
namespace Test
{
@@ -49,12 +51,38 @@ namespace Test
static async Task Main(string[] args)
{
-
- Warehouse.GetTemplateByType(typeof(MyChildRecord));
+ //foreach (var a in ma)
+ // Console.WriteLine(a);
+
+ //var route = "users/{id:int:min(1)}/{name:string}.jpg";
+ //var route = "users/{id}/{name}.jpg";
+ //var rr = getRouteRegex(route);
+
+
+
+ // var m = rr.Match("users/222/fun.jpg");
+
+// Console.WriteLine(m.Value);
+
+ // var escaped = Regex.Escape(route);
+
+ // var replace = Regex.Replace(route, @"\{([^}]*)\}", @"\{([^}]*)\}");
+
+ // var ss = route.Split('{', '}');
+
+ //var regex = "users/\"
+ //Regex regex = new Regex(@"\(([^()]+)\)*");
+
+ //foreach (Match match in regex.Matches("You id is (1) and your number is (0000000000)"))
+ //{
+ // Console.WriteLine(match.Value);
+ //}
// Create stores to keep objects.
var system = await Warehouse.Put("mem", new MemoryStore());
var server = await Warehouse.Put("mem/server", new DistributedServer());
+ var web = await Warehouse.Put("mem/web", new HTTPServer() { Port = 8888});
+
var service = await Warehouse.Put("mem/service", new MyService());
var res1 = await Warehouse.Put("mem/service/r1", new MyResource() { Description = "Testing 1", CategoryId = 10 });
var res2 = await Warehouse.Put("mem/service/r2", new MyResource() { Description = "Testing 2", CategoryId = 11 });
@@ -65,9 +93,20 @@ namespace Test
service.ChildResource = res3;
service.Resources = new MyResource[] { res1, res2, res1 , res3 };
+ //web.MapGet("/{action}/{age}", (int age, string action, HTTPConnection sender) =>
+ //{
+ // Console.WriteLine($"AGE: {age} ACTION: {action}");
+
+ // sender.Response.Number = Esiur.Net.Packets.HTTPResponsePacket.ResponseCode.NotFound;
+ // sender.Send("Not found");
+ //});
+
+ web.MapGet("/", (HTTPConnection sender) => {
+ sender.Send("Hello");
+ });
+
var ok = await Warehouse.Open();
- Console.WriteLine(String.Join(" ", service.Instance.Template.ClassId.ToByteArray()));
// Start testing
TestClient(service);
// TestClient(service);