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")
            };
        }
Example #2
0
        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();
            }
        }