From f25846406370601760eb854ec49ae87dbd1ebdd5 Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Thu, 24 Mar 2022 21:48:51 +0300 Subject: [PATCH] MapGet, ... --- .../Esiur.Stores.EntityCore.csproj | 2 +- .../Esiur.Stores.MongoDB.csproj | 2 +- Esiur/Data/Codec.cs | 3 + Esiur/Esiur.csproj | 2 +- Esiur/Net/HTTP/HTTPServer.cs | 155 +++++++++++++++++- Esiur/Net/IIP/DistributedConnection.cs | 4 +- Esiur/Net/NetworkServer.cs | 2 +- Esiur/Net/Sockets/TCPSocket.cs | 10 +- Esiur/Resource/Template/TypeTemplate.cs | 2 - Test/Program.cs | 45 ++++- 10 files changed, 206 insertions(+), 21 deletions(-) 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);