コード例 #1
0
 //OR  public static IHttpModule Invoke()
 //OR  public IHttpModule Invoke()
 //OR  public IHttpModule Invoke(MethodInfo method)
 public static IHttpModule Invoke(MethodInfo method)
 {
     return(HttpHandler.CreateModule((req, handler) => {
         Console.WriteLine($"Log:{method.Name}");
         return handler.HandleAsync(req);
     }));
 }
コード例 #2
0
 public IHttpHandler Invoke(MethodInfo method)
 {
     if (method.ReturnType == typeof(JsonData) || method.ReturnType == typeof(Task <JsonData>))
     {
         return(HttpHandler.CreateModule((request, handler) =>
         {
             var passport = request.GetPassport();
             if (passport == null)
             {
                 var response = request.CreateResponse();
                 var jsonData = new JsonData
                 {
                     Code = 403,
                     Message = "Not Login"
                 };
                 jsonData.Invoke(request, response);
                 return Task.FromResult(response);
             }
             return handler.HandleAsync(request);
         }));
     }
     else
     {
         return(HttpHandler.CreateModule((request, handler) => {
             var passport = request.GetPassport();
             if (passport == null)
             {
                 var response = request.CreateResponse();
                 response.UseRedirect("/Login");
                 return Task.FromResult(response);
             }
             return handler.HandleAsync(request);
         }));
     }
 }
コード例 #3
0
 public IHttpModule Invoke()
 {
     return(HttpHandler.CreateModule(async(request, handler) => {
         Console.WriteLine("Do Request");
         var response = await handler.HandleAsync(request);
         Console.WriteLine("Do Response");
         return response;
     }));
 }
コード例 #4
0
        public static void Run()
        {
            //testFile
            var testFilePath = "testFile.txt";

            File.WriteAllText(testFilePath, "this is file content.BY 张贺", new UTF8Encoding(false));//No BOM


            var req1 = new HttpRequest("http://localhost:9999/GetJson?Query=Value#Fragment");

            Console.WriteLine(req1);

            var req2 = new HttpRequest("/GetJson?Query=Value#Fragment");

            req2.Url.Scheme    = "http";
            req2.Url.Authority = "localhost:9999";

            var req3 = new HttpRequest();

            req3.Url.AbsoluteUri = "http://localhost:9999/GetJson?Query=Value#Fragment";

            var req4 = new HttpRequest();

            req4.Url.Scheme    = "http";
            req4.Url.Authority = "localhost:9999";
            //OR
            //req4.Url.Host = "localhost";
            //req4.Url.Port = 9999;
            req4.Url.AbsolutePath = "/GetJson?Query=Value#Fragment";
            //OR
            //req4.Url.Path = "/GetJson";
            //req4.Url.Query = "?Query=Value";
            //req4.Url.Fragment = "#Fragment";

            //QueryParams
            req1.Method  = HttpMethod.Get;
            req1.Version = HttpVersion.Version11;
            req1.Headers.Add(HttpHeaders.UserAgent, "My-Client");
            var queryParams1 = new QueryParams();

            queryParams1.Add("Name", "张贺");
            queryParams1.Add("Age", "10");
            queryParams1.Add("Sex", "");
            //OR
            //var queryParams1 = new QueryParams()
            //{
            //    {"Name", "张贺"},
            //    {"Age", "10"},
            //    {"Sex", ""}
            //};
            queryParams1.Parse("TestKey1=TestValue1&TestKey2=TestValue2");
            queryParams1.Join(req1.Url);
            Console.WriteLine(req1);
            var queryParams2 = req1.QueryParams();

            foreach (var item in queryParams2)
            {
                Console.WriteLine($"{item.Key}={item.Value}");
            }
            var     q1      = queryParams2.GetValue <string>("Name");
            var     q2      = queryParams2.GetValue <int>("Age");
            var     q3      = queryParams2.GetValue <int?>("Sex");
            var     qModel1 = queryParams2.GetValue <Model>();
            var     q4      = qModel1.Name;
            var     q5      = qModel1.Age;
            var     q6      = qModel1.Sex;
            dynamic qObj1   = queryParams2.GetValue <DynamicObject>();
            var     q7      = (string)qObj1.Name;
            var     q8      = (int)qObj1.Age;
            var     q9      = (int?)qObj1.Sex;

            //FormParams
            req2.Method  = HttpMethod.Post;
            req2.Version = HttpVersion.Version11;
            req2.Headers[HttpHeaders.UserAgent] = "My-Client";
            var formParams1 = new FormParams();

            formParams1.Add("Name", "张贺1");
            formParams1.Add("Age", "11");
            formParams1.Add("Sex", "");
            //OR
            //var formParams1 = new FormParams()
            //{
            //    {"Name", "张贺1"},
            //    {"Age", "11"},
            //    {"Sex", ""}
            //};
            req2.UseForm(formParams1);
            //OR
            //req2.UseForm(formParams,Encoding.UTF8);
            Console.WriteLine(req2);
            //await
            FeaturesExtensions.ReadFormAsync(req2, 1024 * 1024, 10 * 1024 * 1024).Wait();//1M ,10M
            var formParams2 = req2.FormParams();

            foreach (var item in formParams2)
            {
                Console.WriteLine($"{item.Key}={item.Value}");
            }
            var     f1      = formParams2.GetValue <string>("Name");
            var     f2      = formParams2.GetValue <int>("Age");
            var     f3      = formParams2.GetValue <int?>("Sex");
            var     fModel1 = formParams2.GetValue <Model>();
            var     f4      = fModel1.Name;
            var     f5      = fModel1.Age;
            var     f6      = fModel1.Sex;
            dynamic fObj1   = formParams2.GetValue <DynamicObject>();
            var     f7      = (string)fObj1.Name;
            var     f8      = (int)fObj1.Age;
            var     f9      = (int?)fObj1.Sex;


            //FormParams FormFileParams
            var formParams3 = new FormParams();

            formParams3.Add("Key1", "Value1");
            formParams3.Add("姓名", "张贺");
            var fileParams1 = new FormFileParams();

            fileParams1.Add("Upload1", testFilePath);                                //MimeTypes.Default
            fileParams1.Add("Upload2", "myfile.html", "text/html", new FileInfo(testFilePath));
            fileParams1.Add("Upload3", new BytesFileParams(new byte[] { 1, 2, 3 })); //custom
            req3.UseFormData(formParams3, fileParams1);
            //OR
            //req3.UseFormData(formParams3, fileParams1, "my-random-boundary");
            //req3.UseFormData(formParams3, fileParams1, "my-random-boundary", Encoding.UTF8);
            Console.WriteLine(req3);
            //await
            FeaturesExtensions.ReadFormAsync(req3, 1024 * 1024, 10 * 1024 * 1024).Wait();//1M ,10M
            var formParams4 = req3.FormParams();

            foreach (var item in formParams4)
            {
                Console.WriteLine($"{item.Key}={item.Value}");
            }
            var fileParams2 = req3.FormFileParams();

            foreach (var item in fileParams2)
            {
                Console.WriteLine(item.Key);
                var upload = item.Value;
                Console.WriteLine(upload.Length);
                Console.WriteLine(upload.ContentType);
                Console.WriteLine(upload.FileName);
                upload.TryGetExtension(out var extName);
                Console.WriteLine(extName);
                //await upload.SaveAsync()
            }

            //Cookie
            req4.Headers.Add(HttpHeaders.Cookie, "cookieName1=cookieValue1; cookieName2=cookieValue2");
            var cookieParams1 = req4.CookieParams();

            foreach (var item in cookieParams1)
            {
                Console.WriteLine($"{item.Key}={item.Value}");
            }
            //cookieParams1.GetValue<>
            var sb1 = StringContent.Rent(out var disposable1);

            req4.RegisterForDispose(disposable1);
            sb1.Write("this ");
            sb1.Write(" is Request Content");
            req4.Content = StringContent.Create(sb1.Sequence);
            //OR MemoryContent.Rent()
            Console.WriteLine(req4.Content.ReadStringAsync().Result);//await

            var req5 = new HttpRequest();

            req5.UseJson(new { Data = "Request Json" });
            req5.Headers.TryGetValue(HttpHeaders.ContentType, out var contentType1);
            Console.WriteLine(contentType1);
            Console.WriteLine(req5.Content.ReadStringAsync().Result);//await

            req1.Dispose();
            req2.Dispose();
            req3.Dispose();
            req4.Dispose();
            req5.Dispose();


            var resp1 = new HttpResponse();

            resp1.Headers.Add(HttpHeaders.Server, "My-Web-Server");
            resp1.UseCookie("cookieName1", "cookieValue1");
            resp1.UseCookie("cookieName2", "cookieValue2", domain: "localhost", maxAge: 1000, httpOnly: true, secure: true);
            var cookies1 = resp1.Headers.GetValues(HttpHeaders.SetCookie);

            foreach (var item in cookies1)
            {
                Console.WriteLine(item);
            }


            var resp2 = new HttpResponse();

            resp2.Headers[HttpHeaders.Server] = "My-Web-Server";
            resp2.UseRedirect("http://localhost:9999/Redirect");
            Console.WriteLine(resp2.StatusCode);//302
            resp2.Headers.TryGetValue(HttpHeaders.Location, out var location1);
            Console.WriteLine(location1);


            Console.WriteLine("UseFile");
            var resp3 = new HttpResponse();

            resp3.UseFile(testFilePath);
            Console.WriteLine(resp3.Content.Length);
            Console.WriteLine(resp3.Content.ReadStringAsync().Result);//await
            //UseFile(HttpRequest
            //ETag
            var resp4   = new HttpResponse();
            var etagReq = new HttpRequest();

            resp4.UseFile(etagReq, testFilePath);
            resp4.Headers.TryGetValue(HttpHeaders.AcceptRanges, out var acceptRanges);
            Console.WriteLine(acceptRanges);
            resp4.Headers.TryGetValue(HttpHeaders.ETag, out var etag1);
            Console.WriteLine(etag1);
            //Range
            var resp5    = new HttpResponse();
            var rangeReq = new HttpRequest();

            rangeReq.Headers.Add(HttpHeaders.Range, "bytes=0-3");
            resp5.UseFile(rangeReq, testFilePath);
            Console.WriteLine(resp5.StatusCode);                       //206 Partial Content
            Console.WriteLine(resp5.Content.Length);
            Console.WriteLine(resp5.Content.ReadStringAsync().Result); //await

            var resp6 = new HttpResponse();

            resp6.UseJson(new { Code = 0, Msg = "OK" });
            Console.WriteLine(resp6.Content.ReadStringAsync().Result);//await

            var resp7 = new HttpResponse();
            var sb2   = StringContent.Rent(out var disposable2);

            resp7.RegisterForDispose(disposable2);
            sb1.Write("this ");
            sb1.Write(" is Response Content");
            resp7.Content = StringContent.Create(sb1.Sequence);
            //OR MemoryContent.Rent()
            resp7.Headers.Add(HttpHeaders.ContentType, "text/html; charset=utf-8");
            Console.WriteLine(resp7.Content.ReadStringAsync().Result);//await

            //Compression
            //resp.UseCompression("gzip", 9);//0-9
            //resp.UseCompression("deflate", 9);//0-9
            //resp.UseCompression("br", 11);//0-11

            resp1.Dispose();
            resp2.Dispose();
            resp3.Dispose();
            resp4.Dispose();
            resp5.Dispose();
            resp6.Dispose();
            resp7.Dispose();

            //FeaturesExtensions.RegisterForDispose(req1, resp1);


            //Excpetion
            FeaturesExtensions.UseException((req, resp, ex) => {
                resp.StatusCode = ex.StatusCode() ?? 500;
                resp.Content    = StringContent.Create("ERROR");
                return(Task.CompletedTask);
            });

            //FeaturesExtensions.GetEncoding();
            //FeaturesExtensions.GetReasonPhrase();
            //FeaturesExtensions.GetValue();Register

            Console.WriteLine(HttpVersion.Version9);
            Console.WriteLine(HttpVersion.Version10);
            Console.WriteLine(HttpVersion.Version11);
            Console.WriteLine(HttpVersion.Version20);
            Console.WriteLine(HttpMethod.Get);
            Console.WriteLine(HttpMethod.Put);
            Console.WriteLine(HttpMethod.Post);
            Console.WriteLine(HttpMethod.Head);
            Console.WriteLine(HttpMethod.Trace);
            Console.WriteLine(HttpMethod.Patch);
            Console.WriteLine(HttpMethod.Delete);
            Console.WriteLine(HttpMethod.Options);
            Console.WriteLine(HttpMethod.Connect);
            Console.WriteLine(FeaturesExtensions.GetReasonPhrase(200));
            Console.WriteLine(FeaturesExtensions.GetReasonPhrase(404));

            var queryParam2 = new QueryParams();
            var url         = new Url("http://localhost:9999/Test?q1=v1&q2=v2");

            queryParam2.Parse(url);
            queryParam2.Parse("q3=v3&q4=v4");
            foreach (var item in queryParam2)
            {
                Console.WriteLine($"{item.Key}={item.Value}");
            }


            //HttpHeaders
            Console.WriteLine(HttpHeaders.Accept);
            Console.WriteLine(HttpHeaders.AcceptCharset);
            Console.WriteLine(HttpHeaders.AcceptEncoding);
            Console.WriteLine(HttpHeaders.AcceptLanguage);
            Console.WriteLine(HttpHeaders.AcceptRanges);
            Console.WriteLine(HttpHeaders.AccessControlAllowOrigin);
            //....
            Console.WriteLine(HttpHeaders.Warning);
            Console.WriteLine(HttpHeaders.WwwAuthenticate);

            var contentType2 = "text/json; charset=utf-8; q=0.9; v=1.1";

            HttpHeaders.TryParse(contentType2, out var h1);
            Console.WriteLine(new string(h1));
            HttpHeaders.TryParse(contentType2, out var h2, "charset", out var hv2);
            Console.WriteLine(new string(h2));
            Console.WriteLine(new string(hv2));
            HttpHeaders.TryParse(contentType2, out var h3, "charset", out var hv3, "v", out var hvv3);
            Console.WriteLine(new string(h3));
            Console.WriteLine(new string(hv3));
            Console.WriteLine(new string(hvv3));

            var accept1     = "text/html;q=,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3";
            var acceptSpan1 = accept1.AsSpan();

            while (HttpHeaders.TryParse(ref acceptSpan1, out var a1, "q", out var aq1, "v", out var av1))
            {
                Console.WriteLine(new string(a1));
                if (aq1 != null)
                {
                    Console.WriteLine("q=" + new string(aq1));
                }
                if (av1 != null)
                {
                    Console.WriteLine("v=" + new string(av1));
                }
            }

            //IHttpContent
            IHttpContent testContent = StringContent.Create("{\"Name\":\"Zhang\",\"Age\":30}");

            Console.WriteLine(testContent.Length);
            Console.WriteLine(testContent.Available);
            var length1 = testContent.ComputeLength();//TryComputeLength

            Console.WriteLine(testContent.Length);

            var b1 = testContent.ReadAsync(new byte[1024]);
            var b2 = testContent.ReadAsync(new byte[1024]);

            Console.WriteLine(b1);
            Console.WriteLine(b2);

            Console.WriteLine(testContent.Available);
            testContent.Rewind();
            Console.WriteLine(testContent.Available);
            testContent.DrainAsync().Wait();
            Console.WriteLine(testContent.Available);

            //testContent.ReadJsonAsync<>()
            //testContent.ReadStringAsync();
            //testContent.ReadStreamAsync();
            //testContent.ReadFileAsync();
            //testContent.ReadFormAsync();
            //testContent.ReadFormDataAsync();


            //IHttpHandler
            var handler1 = HttpHandler.Create((req, resp) => {
                Console.WriteLine("handler1");
            });
            var handler2 = HttpHandler.Create(async(req, resp) => {
                await Task.CompletedTask;
                Console.WriteLine("handler2");
            });
            var handler3 = HttpHandler.Create((req) => {
                Console.WriteLine("handler3");
                return(Task.FromResult(new HttpResponse()));
            });
            var handler4 = HttpHandler.Create(async(req) => {
                await Task.CompletedTask;
                Console.WriteLine("handler4");
                return(new HttpResponse());
            });

            handler1.HandleAsync(new HttpRequest()).Wait();
            handler2.HandleAsync(new HttpRequest()).Wait();
            handler3.HandleAsync(new HttpRequest()).Wait();
            handler4.HandleAsync(new HttpRequest()).Wait();


            var module1 = HttpHandler.CreateModule((req, handler) => {
                Console.WriteLine("module1");
                return(handler.HandleAsync(req));
            });
            var module2 = HttpHandler.CreateModule(async(req, handler) => {
                var resp = await handler.HandleAsync(req);
                Console.WriteLine("module2");
                return(resp);
            });
            var handler5 = HttpHandler.Create(async(req) => {
                await Task.CompletedTask;
                Console.WriteLine("handler5");
                return(null);
            });
            var handler6 = HttpHandler.CreatePipeline(new[] { module1, module2, handler5, handler1 });

            handler6.HandleAsync(new HttpRequest()).Wait();
        }
コード例 #5
0
        public static void Run()
        {
            var router = new HttpRouter();

            //var getTree= router.GetTree;
            //var postTree = router.PostTree;
            //var headTree = router.HeadTree;
            //var putTree = router.PutTree;
            //var deleteTree = router.DeleteTree;

            router.MapGet("/get/index", (req, resp) => Console.WriteLine("/get/index"));
            //不支持参数约束,前缀,后缀 繁琐而且用处不大
            //Not support parameter constraints,prefix,suffix tedious and useless
            router.MapGet("/get/{param1}/{param2}", (req, resp) => Console.WriteLine("/get/{param1}/{param2}"));
            router.MapGet("/get/{*catchAll}", (req, resp) => Console.WriteLine("/get/{*catchAll}"));
            Console.WriteLine("MapGet");
            foreach (var item in router.GetTree)
            {
                Console.WriteLine(item.Key);
            }

            //MapAttribute
            var compiler = new HandlerCompiler();//See HandlerCompilerSample

            //compiler.Register()
            router.MapAttribute(new[] { typeof(TestService) }, compiler);
            //customize
            router.MapAttribute(new[] { typeof(TestService) }, compiler,
                                (method, typeHandlers, methodHandlers, handler) =>
            {
                var handlers = new List <IHttpHandler>();
                handlers.Add(HttpHandler.CreateModule((req, handler) =>
                {
                    Console.WriteLine("Before typeHandlers");
                    return(handler.HandleAsync(req));
                }));
                handlers.AddRange(typeHandlers);
                handlers.Add(HttpHandler.CreateModule((req, handler) =>
                {
                    Console.WriteLine("Before methodHandlers");
                    return(handler.HandleAsync(req));
                }));
                handlers.AddRange(methodHandlers);
                handlers.Add(handler);
                return(HttpHandler.CreatePipeline(handlers));
            });
            //router.MapAttribute(compiler);
            //router.MapAttribute(handlerDelegate)
            Console.WriteLine();
            Console.WriteLine("MapAttribute");
            foreach (var item in router.GetTree)
            {
                Console.WriteLine(item.Key);
            }


            Directory.CreateDirectory("Static");
            File.WriteAllText("Static/testFile.txt", "this is file content.BY 张贺", new UTF8Encoding(false));
            File.WriteAllText("Static/testHtml1.html", "<h1>testHtml1<h1>", new UTF8Encoding(false));
            File.WriteAllText("Static/testHtml2.html", "<h2>testHtml2<h2>", new UTF8Encoding(false));
            //MapFile
            router.MapFile("/testFile1", "Static/testFile.txt", 86400);//CacheControl
            router.MapFile("/testFile2", "Static/testFile.txt", "text/html; charset=utf-8", 86400);
            //MapFiles
            router.MapFiles("/static1/{*path}", "Static", 86400);
            var customMimeTypes = new MimeTypes();

            //var customMimeTypes = new MimeTypes(MimeTypes.Default);
            customMimeTypes.Add(".html", "text/html; charset=utf-8");
            router.MapFiles("/static2/{*customName}", "Static", customMimeTypes, 86400, "customName");
            //router.MapFiles("/static2/{*customName}", "Static", MimeTypes.Default, TimeSpan.FromDays(1), "customName");


            //MapSlash
            //尾部/
            router.GetTree.MapSlash();
            //router.MapSlash();
            Console.WriteLine();
            Console.WriteLine("MapSlash");
            foreach (var item in router.GetTree)
            {
                Console.WriteLine(item.Key);
            }

            //动态路由
            //Dynamic change router
            //CopyOnWrite(Safe)
            var newGetTree = new HttpRouter.Tree();

            newGetTree.Map("/new/index", HttpHandler.Create((req, resp) => { Console.WriteLine("/new/index"); }));
            newGetTree.Map("/new/{param1}/{param2}", HttpHandler.Create((req, resp) => { Console.WriteLine("/new/{param1}/{param2}"); }));
            newGetTree.Map("/new/{*catchAll}", HttpHandler.Create((req, resp) => { Console.WriteLine("/new/{*catchAll}"); }));
            newGetTree.MapSlash();
            newGetTree.MapTree(router.GetTree);
            router.GetTree = newGetTree;
            Console.WriteLine();
            Console.WriteLine("NewGetTree");
            foreach (var item in router.GetTree)
            {
                Console.WriteLine(item.Key);
            }

            //Match
            Console.WriteLine();
            Console.WriteLine("Match");
            var params1 = new PathParams();
            var h1      = router.GetTree.Match("/attribute/index", params1);

            Console.WriteLine(params1.Count);
            var params2 = new PathParams();
            var h2      = router.GetTree.Match("/attribute/p1/x/y", params2);

            Console.WriteLine(params2.Count);
            var params3 = new PathParams();
            var h3      = router.GetTree.Match("/attribute/catchAll/x/y/z//", params3);

            Console.WriteLine(params3.Count);

            //HandleAsync
            Console.WriteLine();
            Console.WriteLine("HandleAsync");
            var req1 = new HttpRequest("/attribute/index")
            {
                Method = HttpMethod.Get
            };
            var resp1 = router.HandleAsync(req1).Result;
            var req2  = new HttpRequest("/attribute/p1/x/y")
            {
                Method = HttpMethod.Get
            };
            var resp2 = router.HandleAsync(req2).Result;
            var req3  = new HttpRequest("/attribute/catchAll/x/y/z//")
            {
                Method = HttpMethod.Get
            };
            var resp3 = router.HandleAsync(req3).Result;

            var req4 = new HttpRequest("/testFile1")
            {
                Method = HttpMethod.Get
            };
            var resp4 = router.HandleAsync(req4).Result;

            Console.WriteLine(resp4.Content.ReadStringAsync().Result);
            var req5 = new HttpRequest("/testFile2")
            {
                Method = HttpMethod.Head
            };
            var resp5 = router.HandleAsync(req5).Result;

            Console.WriteLine(resp5.Content.ReadStringAsync().Result);
            var req6 = new HttpRequest("/static1/testHtml1.html")
            {
                Method = HttpMethod.Get
            };
            var resp6 = router.HandleAsync(req6).Result;

            Console.WriteLine(resp6.Content.ReadStringAsync().Result);
            var req7 = new HttpRequest("/static2/testHtml2.html")
            {
                Method = HttpMethod.Get
            };
            var resp7 = router.HandleAsync(req7).Result;

            Console.WriteLine(resp7.Content.ReadStringAsync().Result);


            //------------------------------------------------------------------------
            //router chain(HttpRouter is IHttpHandler)
            var router1 = new HttpRouter();
            var router2 = new HttpRouter();//var tree1 = new HttpRouter.Tree();

            router2.MapGet("/{*path}", (req, resp) => {
                Console.WriteLine(nameof(router2));
                Console.WriteLine(req.PathParams().GetValue <string>("path"));
            });
            router1.GetTree.Map("/Images/{*img}", router2);
            router1.GetTree.Map("/Js/{*js}", HttpHandler.Create(
                                    (req) => {
                Console.WriteLine("Js");
                return(router2.HandleAsync(req));
            }));

            Console.WriteLine();
            var req8 = new HttpRequest("/Images/123456.png")
            {
                Method = HttpMethod.Get
            };
            var resp8 = router1.HandleAsync(req8).Result;
            var req9  = new HttpRequest("/Js/jq.js")
            {
                Method = HttpMethod.Get
            };
            var resp9 = router1.HandleAsync(req9).Result;

            //------------------------------------------------------------------------
            //special
            // /path1/{param1} Match /path1/  (if not Map /path1/)
            var router3 = new HttpRouter();

            router3.MapGet("/", (req, resp) => { Console.WriteLine("/"); });
            router3.MapGet("/{param1}", (req, resp) => { Console.WriteLine("/{param1}"); });
            var req10 = new HttpRequest("/")
            {
                Method = HttpMethod.Get
            };
            var resp10 = router3.HandleAsync(req10).Result;

            var router4 = new HttpRouter();

            //router4.MapGet("/", (req, resp) => { Console.WriteLine("/"); });
            router4.MapGet("/{param1}", (req, resp) => { Console.WriteLine("/{param1}"); });
            var req11 = new HttpRequest("/")
            {
                Method = HttpMethod.Get
            };
            var resp11 = router4.HandleAsync(req11).Result;

            // multiple /
            var router5 = new HttpRouter();

            router5.MapGet("////", (req, resp) => { Console.WriteLine("////"); });
            var req12 = new HttpRequest("////")
            {
                Method = HttpMethod.Get
            };
            var resp12 = router5.HandleAsync(req12).Result;

            router5.MapGet("/Path1/{param1}/{param2}/", (req, resp) => { Console.WriteLine("/Path1/{param1}/{param2}/"); });
            //OR /Path1/{param1}/{param2}/{param3}
            var req13 = new HttpRequest("/Path1///")
            {
                Method = HttpMethod.Get
            };
            var resp13 = router5.HandleAsync(req13).Result;
        }