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 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 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); }
private async Task <HttpRouter> GetRouter() { var resolver = new HttpRouteResolver(); var headMatcher = new HttpFromOwinReqCtxMatcher(); // copy methods and headers as is //using my custom SaaS tenant matcher address matcher headMatcher.Chain(new MatchHostAddressForTenant()); await resolver.AddMatcherAsync(headMatcher, 0); return(new HttpRouter(resolver)); }
// creates an OWIN pipeline that has the router embeded // in it private async Task <HttpRouter> GetRouter() { var resolver = new HttpRouteResolver(); var headMatcher = new HttpFromOwinReqCtxMatcher(); // copy methods and headers as is // route from Owin Server Listening Address to server 2 headMatcher.Chain(new SetAddressListMatcher(RouterTestSuit.Srv02HostNamePort), new HostAddressMatcher(RouterTestSuit.OwinRouterSrvHostNamePort, StringMatchType.UriHostandPortMatch)); await resolver.AddMatcherAsync(headMatcher, 0); return(new HttpRouter(resolver)); }
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 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 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 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)); }
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); }