public async Task MatchNamePortAndSetHostAddress()
        {
            var resolver = new HttpRouteResolver();


            var path = "api/values/0";


            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(headMatcher, 0);

            var router = new HttpRouter(resolver);

            var results = await router.RouteAsync(string.Concat(srv01Address, path));


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv02Address, path), responseString);
        }
        public async Task doHttpPutWithQueryString()
        {
            var resolver = new HttpRouteResolver();

            var path      = "api/models/";
            var sentModel = Model.getRandomModel();



            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Put);

            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new HttpAddSetHeaderMatcher("Content-Type", "application/json"),
                              new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(headMatcher, 0);


            var router  = new HttpRouter(resolver);
            var results = await router.RouteAsync(string.Concat(srv01Address, path, "?ModelId=", sentModel.ModelId), sentModel.asJsonStream());


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            var modelReturn = JsonConvert.DeserializeObject <ModelControllerResponseContent>(responseString);


            Assert.AreEqual(sentModel.ModelId, modelReturn.Models[0].ModelId);
            Assert.AreEqual(string.Concat(srv02Address, path, "?ModelId=", sentModel.ModelId), modelReturn.RequestUri);
        }
        public async Task BasicWiring()
        {
            var resolver = new HttpRouteResolver();


            /*
             * route from bing to microsoft
             *
             */
            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            headMatcher.Chain(new SetAddressListMatcher("www.microsoft.com"),
                              new HostAddressMatcher("www.bing.com", StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(headMatcher, 0);


            var router  = new HttpRouter(resolver);
            var results = await router.RouteAsync("http://www.bing.com");


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            Trace.WriteLine(await responseMessage.Content.ReadAsStringAsync());
        }
        public async Task MatchOnContextUsingCustomValuePredicate()
        {
            var resolver = new HttpRouteResolver();



            var path        = "api/values/0";
            var customKey   = "MyCustomContextKey";
            var customValue = "MyCustomValue";

            // this pluming is to extract which host are we going to use to route


            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            // whenever our custom predicate return true we will route the traffic to server 2
            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new ContextCustomValueMatcher(customKey, (k, v) =>
            {
                var ar = v as string[];
                if (null == ar)
                {
                    return(false);
                }

                if (ar.Length == 3)
                {
                    return(true);
                }

                return(false);
            }));


            await resolver.AddMatcherAsync(headMatcher, 0);

            var router = new HttpRouter(resolver);



            var context = new Dictionary <string, object>();

            // context contains a custom value that is a string array
            context.Add(customKey, new string[] { customValue, customValue, customValue });


            var results = await router.RouteAsync(string.Concat(srv01Address, path), context);


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv02Address, path), responseString);
        }
        public async Task FastestRoute()
        {
            var resolver = new HttpRouteResolver();



            /*
             *  anything point to http://localhost:9001
             *  will be routed as fastest route to
             *  http://locahost:9002 or http://locahost:9003
             *
             *  With HttpGet + Same path
             *
             */



            var path         = "api/randomdelay/0";
            var trytimes     = 5;
            var firstMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            firstMatcher.Chain(new SetAddressListMatcher(new string[] { Srv01HostNamePort, Srv02HostNamePort, Srv03HostNamePort }, false, ContextRoutingType.FastestRoute),
                               new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(firstMatcher, 0);


            var router        = new HttpRouter(resolver);
            var resultsList   = new List <HttpRoutingResult>(trytimes);
            var responsesList = new HashSet <string>();

            // call as many as try times
            for (var i = 1; i <= trytimes; i++)
            {
                resultsList.Add(await router.RouteAsync(string.Concat(srv01Address, path)));
            }

            foreach (var result in resultsList)
            {
                var responseMessage = await result.ResultAsAsync <HttpResponseMessage>();

                var responseString = await responseMessage.Content.ReadAsStringAsync();

                responsesList.Add(responseString);
            }



            // server returns the address
            // in the response
            // any count > 1 means that router is routing to more than one end point
            Assert.AreEqual(true, responsesList.Count > 1);
        }
        public async Task AggregateMultipleEndPoints()
        {
            var resolver = new HttpRouteResolver();


            /*
             *  anything point to http://localhost:9001
             *  will be routed as  be aggregated from multiple backend endpoints
             *
             *  With HttpGet + Same path
             *
             */



            var path  = "api/randomdelay/0";
            var Hosts = 3;



            var firstMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            firstMatcher.Chain(new SetAddressListMatcher(new string[] { Srv01HostNamePort, Srv02HostNamePort, Srv03HostNamePort }, false, ContextRoutingType.ScatterGather),
                               new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(firstMatcher, 0);


            var router = new HttpRouter(resolver);

            var resultsList   = new List <HttpRoutingResult>(Hosts);
            var responsesList = new HashSet <string>();

            // call as many as try times
            var allResults = await router.RouteAsync(string.Concat(srv01Address, path));

            foreach (var result in await allResults.ResultAsAsync <List <HttpResponseMessage> >())
            {
                var responseString = await result.Content.ReadAsStringAsync();

                responsesList.Add(responseString);
            }

            Assert.IsTrue(responsesList.Count == 3); // all hosts in the system
        }
        public async Task RetryThenRoute()
        {
            var resolver = new HttpRouteResolver();



            /*
             *  Attempt to an address (that will fail), then retry after 10 ms, if still failing
             *  it will route to a different server.
             */



            var path = "api/values/0";


            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            headMatcher.Chain(new SetAddressListMatcher("fail"), // point to an address that does not exist (i really hope that you have a machine on your network named "fail")
                              new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(headMatcher, 0);


            var router = new HttpRouter(resolver);

            var headStrategy = new RetryAfterStrategy(10);

            // chain
            headStrategy.ThenRouteToHost(Srv02HostNamePort);

            router.DefaultContextExecuteStrategy = headStrategy;

            var results = await router.RouteAsync(string.Concat(srv01Address, path));


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv02Address, path), responseString);
        }
        public async Task MatchUsingCustomPredicate()
        {
            var resolver = new HttpRouteResolver();



            var path = "api/values/0";



            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            // whenever our custom predicate return true we will route the traffic to server 2

            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new PredicateMatcher((routingctx, address, ctx, body) =>
            {
                return(true);
            }));


            await resolver.AddMatcherAsync(headMatcher, 0);

            var router = new HttpRouter(resolver);



            var context = new Dictionary <string, object>();
            // context contains a custom value that is a string array



            var results = await router.RouteAsync(string.Concat(srv01Address, path), context);


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv02Address, path), responseString);
        }
        public async Task RemoveHeader()
        {
            var resolver = new HttpRouteResolver();



            var path              = "api/Headers/0";
            var customHeaderName  = "customHeader";
            var customHeaderValue = "customHeaderValue";


            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new HttpRemoveHeaderMatcher(customHeaderName),
                              new HttpAddSetHeaderMatcher(customHeaderName, customHeaderValue),
                              new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(headMatcher, 0);


            var router = new HttpRouter(resolver);



            var results = await router.RouteAsync(string.Concat(srv01Address, path));


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();


            var dict = JsonConvert.DeserializeObject <Dictionary <string, IEnumerable <string> > >(responseString);


            // server returns the headers in the response

            Assert.AreEqual(false, dict.ContainsKey(customHeaderName));
        }
        public async Task MatchOnContextContainsKeyWithStringValue()
        {
            var resolver = new HttpRouteResolver();



            var path        = "api/values/0";
            var customKey   = "MyCustomContextKey";
            var customValue = "MyCustomValue";



            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new ContextValueStringMatcher(customKey, customValue, StringMatchType.Exact));


            await resolver.AddMatcherAsync(headMatcher, 0);

            var router = new HttpRouter(resolver);



            var context = new Dictionary <string, object>();

            context.Add(customKey, customValue);


            var results = await router.RouteAsync(string.Concat(srv01Address, path), context);


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv02Address, path), responseString);
        }
        public async Task MatchOnIIFMatcher()
        {
            var resolver = new HttpRouteResolver();



            var path      = "api/values/0";
            var customKey = "MyCustomContextKey";


            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            // Whenever a context contains a key we will route all the traffic to server02
            headMatcher.Chain(

                new IIFMatcher(
                    new ContextContainsKeyMatcher(customKey, StringMatchType.Exact),
                    new SetAddressListMatcher(Srv02HostNamePort),
                    new SetAddressListMatcher(Srv03HostNamePort)
                    )
                );


            await resolver.AddMatcherAsync(headMatcher, 0);

            var router = new HttpRouter(resolver);



            var results = await router.RouteAsync(string.Concat(srv01Address, path));


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv03Address, path), responseString);
        }
        public async Task MatchUsingOrMatcher()
        {
            var resolver = new HttpRouteResolver();



            var path = "api/values/0";

            // if true || False then set address to serve2 and method to get
            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);


            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new OrMatcher(
                                  new FalseMatcher(),
                                  new TrueMatcher()
                                  )
                              );


            await resolver.AddMatcherAsync(headMatcher, 0);


            var router = new HttpRouter(resolver);



            var results = await router.RouteAsync(string.Concat(srv01Address, path));


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv02Address, path), responseString);
        }
        public async Task MatchUsingAndMatcher()
        {
            var resolver = new HttpRouteResolver();


            var path = "api/values/0";

            // if host name = srv1's name and port srv1's port then set the address to server 2 and http method to get.
            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);


            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new AndMatcher(
                                  new HostAddressMatcher(srv01Uri.Port.ToString(), StringMatchType.UriHostPortMatch),
                                  new HostAddressMatcher(srv01Uri.Host, StringMatchType.UriHostNameMatch)
                                  )
                              );


            await resolver.AddMatcherAsync(headMatcher, 0);


            var router = new HttpRouter(resolver);



            var results = await router.RouteAsync(string.Concat(srv01Address, path));


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv02Address, path), responseString);
        }
        public async Task BasicTelemetry()
        {
            var resolver = new HttpRouteResolver();



            var path = "api/values/0";
            // this pluming is to extract which host are we going to use to route


            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(headMatcher, 0);


            var router = new HttpRouter(resolver);



            var results = await router.RouteAsync(string.Concat(srv01Address, path));


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv02Address, path), responseString);
            Assert.IsTrue(router.TotalExecutedLastMin > 0);
            Assert.IsTrue(router.TotalResolvedLastMin > 0);
        }
        public async Task OverrideSchemeAndPath()
        {
            var resolver = new HttpRouteResolver();



            var path = "api/values/0";

            /*
             *  route to server 2 override the scheme to http & path to a static path
             */


            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new HttpOverridePathMatcher("/api/values/0"),
                              new HttpOverrideSchemeMatcher("http"),
                              new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(headMatcher, 0);

            var router = new HttpRouter(resolver);

            var results = await router.RouteAsync(string.Concat("xxx://", Srv01HostNamePort)); // bad scehme & no path

            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();

            // server returns the address
            // in the response

            Assert.AreEqual(string.Concat(srv02Address, path), responseString);
        }
        public async Task SimpleLoadBalance()
        {
            var resolver = new HttpRouteResolver();



            /*
             *  anything point to http://localhost:9001
             *  will be routed R/R balanced to
             *  http://locahost:9001
             *  http://locahost:9002
             *  http://locahost:9003
             *
             *  With HttpGet + Same path
             */



            var path     = "/api/values/0";
            var trytimes = 3;



            var firstMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            firstMatcher.Chain(new SetAddressListMatcher(new string[] { Srv01HostNamePort, Srv02HostNamePort, Srv03HostNamePort }, false, ContextRoutingType.RoundRobin),
                               new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(firstMatcher, 0);


            var router = new HttpRouter(resolver);



            var resultsList   = new List <HttpRoutingResult>(trytimes);
            var responsesList = new HashSet <string>();

            // call as many as try times
            for (var i = 1; i <= trytimes; i++)
            {
                resultsList.Add(await router.RouteAsync(string.Concat(srv01Address, path)));
            }

            foreach (var result in resultsList)
            {
                var responseMessage = await result.ResultAsAsync <HttpResponseMessage>();

                var responseString = await responseMessage.Content.ReadAsStringAsync();

                responsesList.Add(responseString);
            }


            // response list should contain
            // http <server1> + path
            // http <server2> + path
            // http <server3> + path



            var expectedList = new List <string>()
            {
                string.Concat("http://", Srv01HostNamePort, path),
                string.Concat("http://", Srv02HostNamePort, path),
                string.Concat("http://", Srv03HostNamePort, path)
            };

            foreach (var response in responsesList)
            {
                if (expectedList.Contains(response))
                {
                    expectedList.Remove(response);
                }
            }

            Assert.IsTrue(expectedList.Count == 0); // all hosts in the system
        }
        public async Task LongLoadBalance()
        {
            var resolver = new HttpRouteResolver();


            /*
             *  anything point to http://localhost:9001
             *  will be routed R/R balanced to
             *  http://locahost:9001
             *  http://locahost:9002
             *  http://locahost:9003
             *
             *  With HttpGet + Same path
             */



            var path     = "/api/values/0";
            var trytimes = 9;
            // this pluming is to extract which host are we going to use to route



            var firstMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            firstMatcher.Chain(new SetAddressListMatcher(new string[] { Srv01HostNamePort, Srv02HostNamePort, Srv03HostNamePort }, false, ContextRoutingType.RoundRobin),
                               new HostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(firstMatcher, 0);


            var router = new HttpRouter(resolver);



            var resultsList   = new List <HttpRoutingResult>(trytimes);
            var responsesList = new Dictionary <string, int>();

            // call as many as try times
            for (var i = 1; i <= trytimes; i++)
            {
                resultsList.Add(await router.RouteAsync(string.Concat(srv01Address, path)));
            }

            foreach (var result in resultsList)
            {
                var responseMessage = await result.ResultAsAsync <HttpResponseMessage>();

                var responseString = await responseMessage.Content.ReadAsStringAsync();

                if (!responsesList.ContainsKey(responseString))
                {
                    responsesList.Add(responseString, 1);
                }
                else
                {
                    responsesList[responseString] = ++responsesList[responseString];
                }
            }

            var bSucess = true;

            // validate that each is called exactly 3 times
            foreach (var key in responsesList.Keys)
            {
                if (responsesList[key] != 3)
                {
                    bSucess = false;
                    break;
                }
            }



            Assert.IsTrue(bSucess); // all hosts in the system
        }
        public async Task AllTelemetry()
        {
            Trace.WriteLine("This test expects router's min clicker to trim every 5 sec");

            var resolver = new HttpRouteResolver();


            // simple routing to ensure that resolver routing algorthim is working

            /*
             *  Route all requests from Server 1 to Server 2
             *
             */



            var path = "api/values/0";
            // this pluming is to extract which host are we going to use to route


            var headMatcher = new HttpSetMethodMatcher(HttpMethod.Get);

            headMatcher.Chain(new SetAddressListMatcher(Srv02HostNamePort),
                              new IsHostAddressMatcher(Srv01HostNamePort, StringMatchType.UriHostandPortMatch));


            await resolver.AddMatcherAsync(headMatcher, 0);


            var router = new HttpRouter.Core.HttpRouter(resolver);

            router.DefaultCallHandlingStratgy = new RetryStrategy(100);

            var results = await router.RouteAsync(string.Concat(srv01Address, path));


            var responseMessage = await results.ResultAsAsync <HttpResponseMessage>();

            var responseString = await responseMessage.Content.ReadAsStringAsync();



            Assert.AreEqual(string.Concat(srv02Address, path), responseString);

            var TotalExecutedLastMin = router.TotalExecutedLastMin;
            var TotalResolvedLastMin = router.TotalResolvedLastMin;


            Assert.IsTrue(TotalExecutedLastMin > 0);
            Assert.IsTrue(TotalResolvedLastMin > 0);

            await Task.Delay(TimeSpan.FromSeconds(61)); // wait for at least one trim to happen (from min clicker to hour cliker, every min)

            var TotalExecutedLastHour = router.TotalExecutedLastHour;
            var TotalResolvedLastHour = router.TotalResolvedLastHour;

            var AvgExecuteTimePerMinLastHour = router.AvgExecuteTimePerMinLastHour;
            var AvgResolveTimePerMinLastHour = router.AvgResolveTimePerMinLastHour;


            Assert.IsTrue(TotalExecutedLastHour > 0);
            Assert.IsTrue(TotalResolvedLastHour > 0);


            Assert.IsTrue(AvgExecuteTimePerMinLastHour > 0);
            Assert.IsTrue(AvgResolveTimePerMinLastHour > 0);

            // Write
            Trace.WriteLine(string.Concat("TotalExecutedLastMin: ", TotalExecutedLastMin));
            Trace.WriteLine(string.Concat("TotalResolvedLastMin: ", TotalResolvedLastMin));
            Trace.WriteLine(string.Concat("TotalExecutedLastHour: ", TotalExecutedLastHour));
            Trace.WriteLine(string.Concat("TotalResolvedLastHour: ", TotalResolvedLastHour));
            Trace.WriteLine(string.Concat("AvgExecuteTimePerMinLastHour: ", AvgExecuteTimePerMinLastHour));
            Trace.WriteLine(string.Concat("AvgResolveTimePerMinLastHour: ", AvgResolveTimePerMinLastHour));
        }
Example #19
0
        private async Task <HttpRouter> GetRouter()
        {
            /*
             * factory create a instance of SocketSession for incoming connection.
             * in this test we will create a router attached it to the factory (which is injected in every socket session)
             *
             */

            // prepare the router
            var resolver = new HttpRouteResolver();


            // routing logic

            //-> If context contains GetModels (route to backend(s), fastest route, add scheme, add path, ignore body, set HttpMethod to Get)


            var getModelsMatchers = new HttpSetMethodMatcher(HttpMethod.Get);

            getModelsMatchers.Chain(new IgnoreSourceBodyStreamMatcher(),                                                                                                             // ignore whatever message body provided by the socket.
                                    new SetAddressListMatcher(new string[] { RouterTestSuit.Srv01HostNamePort, RouterTestSuit.Srv02HostNamePort, RouterTestSuit.Srv03HostNamePort }, // address list
                                                              true,                                                                                                                  // clear whatever there
                                                              ContextRoutingType.FastestRoute),                                                                                      // fastest
                                    new HttpOverridePathMatcher("/api/models/"),                                                                                                     // add path
                                    new HttpOverrideSchemeMatcher("http"),                                                                                                           // add scheme
                                    new ContextValueStringMatcher("Message.Type", "GetModels"));



            //-> If context contains AddModels
            var addModelsMatcher = new HttpSetMethodMatcher(HttpMethod.Post);

            addModelsMatcher.Chain(
                new SetAddressListMatcher(RouterTestSuit.Srv01HostNamePort),     // set address to Server1
                new HttpAddSetHeaderMatcher("Content-Type", "application/json"), // my socket puts everything as json
                new HttpOverridePathMatcher("/api/models/"),                     // add path
                new HttpOverrideSchemeMatcher("http"),                           // add scheme
                new ContextValueStringMatcher("Message.Type", "AddModels")
                );



            // There are multiple ways i can do use the above matchers

            /* method 1) use Or matcher
             *  var orMatcher = new OrMatcher(getModelsMatchers, addModelsMatcher);
             *  await resolver.AddMatcherAsync(orMatcher, 0);
             */

            /* method 2) use AnyMatcher
             *  var anyMatcher = new AnyMatcher(getModelsMatchers, addModelsMatcher);
             *  await resolver.AddMatcherAsync(anyMatcher, 0);
             */

            // method 3) use the  new ContextValueStringMatcher("Message.Type", "AddModels") in an IIF matcher (remember to remove them from Add/Get matcher variables above).


            // or just create differet matchers in resolvers. the advantages, if each tree wants to cache and have state on thier
            // they will do that without conficlts (check how load balanacer is used in HttpRoutingContext).

            await resolver.AddMatcherAsync(getModelsMatchers, 0);

            await resolver.AddMatcherAsync(addModelsMatcher, 1);

            var router = new HttpRouter(resolver);

            return(router);
        }