private static HttpClient CreateHttpClient(Func<int> getMaxBytesPerSecond, int forceConcurrentCount) { // This blocks client responses until the number of concurrent clients // has reached the desired value. var tcs = new TaskCompletionSource<int>(); Action requestReceived = () => { if (Interlocked.Decrement(ref forceConcurrentCount) == 0) { tcs.SetResult(0); } }; var app = new AppBuilder(); app.MaxBandwidthGlobal(getMaxBytesPerSecond) .Use(async (context, _) => { requestReceived(); var delayTask = Task.Delay(5000); if (await Task.WhenAny(delayTask, tcs.Task) == delayTask) { throw new TimeoutException("Timedout waiting for concurrent clients."); } byte[] bytes = Enumerable.Repeat((byte) 0x1, 1024).ToArray(); const int batches = 4; context.Response.StatusCode = 200; context.Response.ReasonPhrase = "OK"; context.Response.ContentLength = bytes.LongLength * batches; context.Response.ContentType = "application/octet-stream"; for (int i = 0; i < batches; i++) { await Task.Delay(1); //forces actual asynchrony await context.Response.Body.WriteAsync(bytes, 0, bytes.Length); } }); return new HttpClient(new OwinHttpMessageHandler(app.Build())) { BaseAddress = new Uri("http://example.com") }; }
private static void Main(string[] args) { Log.Logger = new LoggerConfiguration() .WriteTo .Console() .MinimumLevel.Verbose() .CreateLogger(); var app = new AppBuilder(); app.MaxUrlLength(100); app.MaxQueryStringLength(80); app.MaxConcurrentRequests(4); app.MinResponseDelay(context => { var queryParams = HttpUtility.ParseQueryString(context.Uri.Query); var minResponseDelayParam = queryParams.Get("minresponsedelay"); int minResponseDelay; return int.TryParse(minResponseDelayParam, out minResponseDelay) ? TimeSpan.FromSeconds(minResponseDelay) : TimeSpan.Zero; }); app.MaxBandwidthPerRequest(context => { var queryParams = HttpUtility.ParseQueryString(context.Uri.Query); var maxBandwidthParam = queryParams.Get("maxbandwidthperrequest"); int maxBandwidth; return int.TryParse(maxBandwidthParam, out maxBandwidth) ? maxBandwidth : -1; }); app.MaxBandwidthGlobal(10 * 1024 * 1024); app.Use(async (context, next) => { if(!context.Request.Uri.AbsolutePath.Equals("/file", StringComparison.OrdinalIgnoreCase)) { await next(); return; } int size; if(!int.TryParse(context.Request.Query.Get("size"), out size)) { await next(); return; } context.Response.ContentLength = size; context.Response.ContentType = "application/octect-stream"; context.Response.StatusCode = 200; context.Response.ReasonPhrase = "OK"; var buffer = new byte[16384]; int count = 0; while(count < size) { int length = Math.Min(buffer.Length, size - count); await context.Response.WriteAsync(buffer, 0, length, context.Request.CallCancelled); count += length; } }); app.Use(async (context, next) => { context.Response.ContentType = "text/html"; context.Response.StatusCode = 200; context.Response.ReasonPhrase = "OK"; var index = File.ReadAllText("index.html"); await context.Response.WriteAsync(index); }); var server = ServerBuilder.New() .SetEndPoint(new IPEndPoint(IPAddress.Loopback, 8080)) .SetOwinApp(app.Build()); using(server.Build()) { server.Start(); Process.Start("http://localhost:8080"); Log.Information("Server running http://localhost:8080"); Console.ReadLine(); } }