public async Task LargeMultipartUpload()
        {
            var port    = PortManager.GetPort();
            var builder = new WebHostBuilder()
                          .UseKestrel()
                          .UseUrls($"http://localhost:{port}/")
                          .Configure(app =>
            {
                app.Run(async context =>
                {
                    long total = 0;
                    var bytes  = new byte[1024];
                    var count  = await context.Request.Body.ReadAsync(bytes, 0, bytes.Length);
                    while (count > 0)
                    {
                        total += count;
                        count  = await context.Request.Body.ReadAsync(bytes, 0, bytes.Length);
                    }
                    await context.Response.WriteAsync(total.ToString(CultureInfo.InvariantCulture));
                });
            });

            using (var host = builder.Build())
            {
                host.Start();

                using (var client = new HttpClient())
                {
                    using (var form = new MultipartFormDataContent())
                    {
                        const int oneMegabyte = 1024 * 1024;
                        const int files       = 2048;
                        var       bytes       = new byte[oneMegabyte];

                        for (int i = 0; i < files; i++)
                        {
                            var fileName = Guid.NewGuid().ToString();
                            form.Add(new ByteArrayContent(bytes), "file", fileName);
                        }

                        var length   = form.Headers.ContentLength.Value;
                        var response = await client.PostAsync($"http://localhost:{port}/", form);

                        response.EnsureSuccessStatusCode();
                        Assert.Equal(length.ToString(CultureInfo.InvariantCulture), await response.Content.ReadAsStringAsync());
                    }
                }
            }
        }
        public async Task LargeUpload()
        {
            var port    = PortManager.GetPort();
            var builder = new WebHostBuilder()
                          .UseKestrel()
                          .UseUrls($"http://localhost:{port}/")
                          .Configure(app =>
            {
                app.Run(async context =>
                {
                    // Read the full request body
                    var total = 0;
                    var bytes = new byte[1024];
                    var count = await context.Request.Body.ReadAsync(bytes, 0, bytes.Length);
                    while (count > 0)
                    {
                        for (int i = 0; i < count; i++)
                        {
                            Assert.Equal(total % 256, bytes[i]);
                            total++;
                        }
                        count = await context.Request.Body.ReadAsync(bytes, 0, bytes.Length);
                    }

                    await context.Response.WriteAsync(total.ToString(CultureInfo.InvariantCulture));
                });
            });

            using (var host = builder.Build())
            {
                host.Start();

                using (var client = new HttpClient())
                {
                    var bytes = new byte[1024 * 1024];
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        bytes[i] = (byte)i;
                    }

                    var response = await client.PostAsync($"http://localhost:{port}/", new ByteArrayContent(bytes));

                    response.EnsureSuccessStatusCode();
                    var sizeString = await response.Content.ReadAsStringAsync();

                    Assert.Equal(sizeString, bytes.Length.ToString(CultureInfo.InvariantCulture));
                }
            }
        }
        public async Task IgnoreNullHeaderValues(string headerName, StringValues headerValue, string expectedValue)
        {
            var port   = PortManager.GetPort();
            var config = new ConfigurationBuilder()
                         .AddInMemoryCollection(new Dictionary <string, string>
            {
                { "server.urls", $"http://localhost:{port}/" }
            })
                         .Build();

            var hostBuilder = new WebHostBuilder()
                              .UseConfiguration(config)
                              .UseKestrel()
                              .Configure(app =>
            {
                app.Run(async context =>
                {
                    context.Response.Headers.Add(headerName, headerValue);

                    await context.Response.WriteAsync("");
                });
            });

            using (var host = hostBuilder.Build())
            {
                host.Start();

                using (var client = new HttpClient())
                {
                    var response = await client.GetAsync($"http://localhost:{port}/");

                    response.EnsureSuccessStatusCode();

                    var headers = response.Headers;

                    if (expectedValue == null)
                    {
                        Assert.False(headers.Contains(headerName));
                    }
                    else
                    {
                        Assert.True(headers.Contains(headerName));
                        Assert.Equal(headers.GetValues(headerName).Single(), expectedValue);
                    }
                }
            }
        }
        public async Task ZeroToTenThreads(int threadCount)
        {
            var port   = PortManager.GetPort();
            var config = new ConfigurationBuilder()
                         .AddInMemoryCollection(new Dictionary <string, string>
            {
                { "server.urls", $"http://localhost:{port}/" }
            })
                         .Build();

            var hostBuilder = new WebHostBuilder()
                              .UseConfiguration(config)
                              .UseKestrel(options =>
            {
                options.ThreadCount = threadCount;
            })
                              .Configure(app =>
            {
                app.Run(context =>
                {
                    return(context.Response.WriteAsync("Hello World"));
                });
            });

            using (var host = hostBuilder.Build())
            {
                host.Start();

                using (var client = new HttpClient())
                {
                    // Send 20 requests just to make sure we don't get any failures
                    var requestTasks = new List <Task <string> >();
                    for (int i = 0; i < 20; i++)
                    {
                        var requestTask = client.GetStringAsync($"http://localhost:{port}/");
                        requestTasks.Add(requestTask);
                    }

                    foreach (var result in await Task.WhenAll(requestTasks))
                    {
                        Assert.Equal("Hello World", result);
                    }
                }
            }
        }
        public void RequestPathIsNormalized()
        {
            var port    = PortManager.GetPort();
            var builder = new WebHostBuilder()
                          .UseKestrel()
                          .UseUrls($"http://localhost:{port}/\u0041\u030A")
                          .Configure(app =>
            {
                app.Run(async context =>
                {
                    var connection = context.Connection;
                    Assert.Equal("/\u00C5", context.Request.PathBase.Value);
                    Assert.Equal("/B/\u00C5", context.Request.Path.Value);
                    await context.Response.WriteAsync("hello, world");
                });
            });

            using (var host = builder.Build())
            {
                host.Start();

                using (var socket = TestConnection.CreateConnectedLoopbackSocket(port))
                {
                    socket.Send(Encoding.ASCII.GetBytes("GET /%41%CC%8A/A/../B/%41%CC%8A HTTP/1.1\r\n\r\n"));
                    socket.Shutdown(SocketShutdown.Send);

                    var response = new StringBuilder();
                    var buffer   = new byte[4096];
                    while (true)
                    {
                        var length = socket.Receive(buffer);
                        if (length == 0)
                        {
                            break;
                        }

                        response.Append(Encoding.ASCII.GetString(buffer, 0, length));
                    }

                    Assert.StartsWith("HTTP/1.1 200 OK", response.ToString());
                }
            }
        }
        private async Task TestPathBase(string registerPathBase, string requestPath, string expectedPathBase, string expectedPath)
        {
            var port   = PortManager.GetPort();
            var config = new ConfigurationBuilder().AddInMemoryCollection(
                new Dictionary <string, string> {
                { "server.urls", $"http://localhost:{port}{registerPathBase}" }
            }).Build();

            var builder = new WebHostBuilder()
                          .UseConfiguration(config)
                          .UseKestrel()
                          .Configure(app =>
            {
                app.Run(async context =>
                {
                    await context.Response.WriteAsync(JsonConvert.SerializeObject(new
                    {
                        PathBase = context.Request.PathBase.Value,
                        Path     = context.Request.Path.Value
                    }));
                });
            });

            using (var host = builder.Build())
            {
                host.Start();

                using (var client = new HttpClient())
                {
                    var response = await client.GetAsync($"http://localhost:{port}{requestPath}");

                    response.EnsureSuccessStatusCode();

                    var responseText = await response.Content.ReadAsStringAsync();

                    Assert.NotEmpty(responseText);

                    var pathFacts = JsonConvert.DeserializeObject <JObject>(responseText);
                    Assert.Equal(expectedPathBase, pathFacts["PathBase"].Value <string>());
                    Assert.Equal(expectedPath, pathFacts["Path"].Value <string>());
                }
            }
        }
        public async Task OnCompleteCalledEvenWhenOnStartingNotCalled()
        {
            var port   = PortManager.GetPort();
            var config = new ConfigurationBuilder()
                         .AddInMemoryCollection(new Dictionary <string, string>
            {
                { "server.urls", $"http://localhost:{port}/" }
            })
                         .Build();

            var onStartingCalled  = false;
            var onCompletedCalled = false;

            var hostBuilder = new WebHostBuilder()
                              .UseConfiguration(config)
                              .UseKestrel()
                              .Configure(app =>
            {
                app.Run(context =>
                {
                    context.Response.OnStarting(() => Task.Run(() => onStartingCalled   = true));
                    context.Response.OnCompleted(() => Task.Run(() => onCompletedCalled = true));

                    // Prevent OnStarting call (see Frame<T>.RequestProcessingAsync()).
                    throw new Exception();
                });
            });

            using (var host = hostBuilder.Build())
            {
                host.Start();

                using (var client = new HttpClient())
                {
                    var response = await client.GetAsync($"http://localhost:{port}/");

                    Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
                    Assert.False(onStartingCalled);
                    Assert.True(onCompletedCalled);
                }
            }
        }
        private async Task TestRemoteIPAddress(string registerAddress, string requestAddress, string expectAddress)
        {
            var port    = PortManager.GetPort();
            var builder = new WebHostBuilder()
                          .UseKestrel()
                          .UseUrls($"http://{registerAddress}:{port}")
                          .Configure(app =>
            {
                app.Run(async context =>
                {
                    var connection = context.Connection;
                    await context.Response.WriteAsync(JsonConvert.SerializeObject(new
                    {
                        RemoteIPAddress = connection.RemoteIpAddress?.ToString(),
                        RemotePort      = connection.RemotePort,
                        LocalIPAddress  = connection.LocalIpAddress?.ToString(),
                        LocalPort       = connection.LocalPort
                    }));
                });
            });

            using (var host = builder.Build())
                using (var client = new HttpClient())
                {
                    host.Start();

                    var response = await client.GetAsync($"http://{requestAddress}:{port}/");

                    response.EnsureSuccessStatusCode();

                    var connectionFacts = await response.Content.ReadAsStringAsync();

                    Assert.NotEmpty(connectionFacts);

                    var facts = JsonConvert.DeserializeObject <JObject>(connectionFacts);
                    Assert.Equal(expectAddress, facts["RemoteIPAddress"].Value <string>());
                    Assert.NotEmpty(facts["RemotePort"].Value <string>());
                }
        }