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 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 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 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 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 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 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 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 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 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 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
        }