Example #1
0
        public async Task DoesNotOverrideDirectConfigurationWithIServerAddressesFeature_IfPreferHostingUrlsFalse()
        {
            var useUrlsAddress = $"http://127.0.0.1:0";

            var hostBuilder = TransportSelector.GetWebHostBuilder()
                              .ConfigureServices(AddTestLogging)
                              .UseKestrel(options =>
            {
                options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
                {
                    listenOptions.UseHttps(TestResources.TestCertificatePath, "testPassword");
                });
            })
                              .UseUrls($"http://127.0.0.1:0")
                              .PreferHostingUrls(false)
                              .Configure(ConfigureEchoAddress);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                var port = host.GetPort();

                // If this isn't working properly, we'll get the HTTP endpoint defined in UseUrls
                // instead of the HTTPS endpoint defined in UseKestrel.
                var serverAddresses = host.ServerFeatures.Get <IServerAddressesFeature>().Addresses;
                Assert.Equal(1, serverAddresses.Count);
                var endPointAddress = $"https://127.0.0.1:{port}";
                Assert.Equal(serverAddresses.First(), endPointAddress);

                Assert.Single(TestApplicationErrorLogger.Messages, log => log.LogLevel == LogLevel.Warning &&
                              string.Equals(CoreStrings.FormatOverridingWithKestrelOptions(useUrlsAddress, "UseKestrel()"),
                                            log.Message, StringComparison.Ordinal));

                Assert.Equal(new Uri(endPointAddress).ToString(), await HttpClientSlim.GetStringAsync(endPointAddress, validateCertificate: false));
                await host.StopAsync();
            }
        }
Example #2
0
        public async Task CanRebindToEndPoint()
        {
            var port            = GetNextPort();
            var endPointAddress = $"http://127.0.0.1:{port}/";

            var hostBuilder = TransportSelector.GetWebHostBuilder()
                              .ConfigureServices(AddTestLogging)
                              .UseKestrel(options =>
            {
                options.Listen(IPAddress.Loopback, port);
            })
                              .Configure(ConfigureEchoAddress);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                Assert.Equal(endPointAddress, await HttpClientSlim.GetStringAsync(endPointAddress));

                await host.StopAsync();
            }

            hostBuilder = TransportSelector.GetWebHostBuilder()
                          .UseKestrel(options =>
            {
                options.Listen(IPAddress.Loopback, port);
            })
                          .Configure(ConfigureEchoAddress);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                Assert.Equal(endPointAddress, await HttpClientSlim.GetStringAsync(endPointAddress));

                await host.StopAsync();
            }
        }
Example #3
0
        public async Task OverrideDirectConfigurationWithIServerAddressesFeature_Succeeds()
        {
            var useUrlsAddress = $"http://127.0.0.1:0";
            var hostBuilder    = TransportSelector.GetWebHostBuilder()
                                 .UseKestrel(options =>
            {
                options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
                {
                    listenOptions.UseHttps(TestResources.GetTestCertificate());
                });
            })
                                 .UseUrls(useUrlsAddress)
                                 .PreferHostingUrls(true)
                                 .ConfigureServices(AddTestLogging)
                                 .Configure(ConfigureEchoAddress);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                var port = host.GetPort();

                // If this isn't working properly, we'll get the HTTPS endpoint defined in UseKestrel
                // instead of the HTTP endpoint defined in UseUrls.
                var serverAddresses = host.ServerFeatures.Get <IServerAddressesFeature>().Addresses;
                Assert.Equal(1, serverAddresses.Count);
                var useUrlsAddressWithPort = $"http://127.0.0.1:{port}";
                Assert.Equal(serverAddresses.First(), useUrlsAddressWithPort);

                Assert.Single(TestApplicationErrorLogger.Messages, log => log.LogLevel == LogLevel.Information &&
                              string.Equals(CoreStrings.FormatOverridingWithPreferHostingUrls(nameof(IServerAddressesFeature.PreferHostingUrls), useUrlsAddress),
                                            log.Message, StringComparison.Ordinal));

                Assert.Equal(new Uri(useUrlsAddressWithPort).ToString(), await HttpClientSlim.GetStringAsync(useUrlsAddressWithPort));

                await host.StopAsync();
            }
        }
Example #4
0
        public void ThrowsWhenBindingToIPv6AddressInUse()
        {
            TestApplicationErrorLogger.IgnoredExceptions.Add(typeof(IOException));

            using (var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
            {
                socket.Bind(new IPEndPoint(IPAddress.IPv6Loopback, 0));
                socket.Listen(0);
                var port = ((IPEndPoint)socket.LocalEndPoint).Port;

                var hostBuilder = TransportSelector.GetWebHostBuilder()
                                  .ConfigureServices(AddTestLogging)
                                  .UseKestrel()
                                  .UseUrls($"http://[::1]:{port}")
                                  .Configure(ConfigureEchoAddress);

                using (var host = hostBuilder.Build())
                {
                    var exception = Assert.Throws <IOException>(() => host.Start());
                    Assert.Equal(CoreStrings.FormatEndpointAlreadyInUse($"http://[::1]:{port}"), exception.Message);
                }
            }
        }
Example #5
0
        private async Task RegisterDefaultServerAddresses_Success(IEnumerable <string> addresses, bool mockHttps = false)
        {
            var hostBuilder = TransportSelector.GetWebHostBuilder()
                              .ConfigureServices(AddTestLogging)
                              .UseKestrel(options =>
            {
                if (mockHttps)
                {
                    options.DefaultCertificate = TestResources.GetTestCertificate();
                }
            })
                              .Configure(ConfigureEchoAddress);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                Assert.Equal(5000, host.GetPort());

                if (mockHttps)
                {
                    Assert.Contains(5001, host.GetPorts());
                }

                Assert.Single(TestApplicationErrorLogger.Messages, log => log.LogLevel == LogLevel.Debug &&
                              (string.Equals(CoreStrings.FormatBindingToDefaultAddresses(Constants.DefaultServerAddress, Constants.DefaultServerHttpsAddress), log.Message, StringComparison.Ordinal) ||
                               string.Equals(CoreStrings.FormatBindingToDefaultAddress(Constants.DefaultServerAddress), log.Message, StringComparison.Ordinal)));

                foreach (var address in addresses)
                {
                    Assert.Equal(new Uri(address).ToString(), await HttpClientSlim.GetStringAsync(address, validateCertificate: false));
                }

                await host.StopAsync();
            }
        }
Example #6
0
        private void ThrowsWhenBindingLocalhostToAddressInUse(AddressFamily addressFamily)
        {
            TestApplicationErrorLogger.IgnoredExceptions.Add(typeof(IOException));

            var addressInUseCount = 0;
            var wrongMessageCount = 0;

            var address            = addressFamily == AddressFamily.InterNetwork ? IPAddress.Loopback : IPAddress.IPv6Loopback;
            var otherAddressFamily = addressFamily == AddressFamily.InterNetwork ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork;

            while (addressInUseCount < 10 && wrongMessageCount < 10)
            {
                int port;

                using (var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
                {
                    // Bind first to IPv6Any to ensure both the IPv4 and IPv6 ports are available.
                    socket.Bind(new IPEndPoint(IPAddress.IPv6Any, 0));
                    socket.Listen(0);
                    port = ((IPEndPoint)socket.LocalEndPoint).Port;
                }

                using (var socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp))
                {
                    try
                    {
                        socket.Bind(new IPEndPoint(address, port));
                        socket.Listen(0);
                    }
                    catch (SocketException)
                    {
                        addressInUseCount++;
                        continue;
                    }

                    var hostBuilder = TransportSelector.GetWebHostBuilder()
                                      .ConfigureServices(AddTestLogging)
                                      .UseKestrel()
                                      .UseUrls($"http://localhost:{port}")
                                      .Configure(ConfigureEchoAddress);

                    using (var host = hostBuilder.Build())
                    {
                        var exception = Assert.Throws <IOException>(() => host.Start());

                        var thisAddressString  = $"http://{(addressFamily == AddressFamily.InterNetwork ? "127.0.0.1" : "[::1]")}:{port}";
                        var otherAddressString = $"http://{(addressFamily == AddressFamily.InterNetworkV6? "127.0.0.1" : "[::1]")}:{port}";

                        if (exception.Message == CoreStrings.FormatEndpointAlreadyInUse(otherAddressString))
                        {
                            // Don't fail immediately, because it's possible that something else really did bind to the
                            // same port for the other address family between the IPv6Any bind above and now.
                            wrongMessageCount++;
                            continue;
                        }

                        Assert.Equal(CoreStrings.FormatEndpointAlreadyInUse(thisAddressString), exception.Message);
                        break;
                    }
                }
            }

            if (addressInUseCount >= 10)
            {
                Assert.True(false, $"The corresponding {otherAddressFamily} address was already in use 10 times.");
            }

            if (wrongMessageCount >= 10)
            {
                Assert.True(false, $"An error for a conflict with {otherAddressFamily} was thrown 10 times.");
            }
        }
Example #7
0
        public async Task LargeUpload(long contentLength, bool checkBytes)
        {
            const int bufferLength = 1024 * 1024;

            Assert.True(contentLength % bufferLength == 0, $"{nameof(contentLength)} sent must be evenly divisible by {bufferLength}.");
            Assert.True(bufferLength % 256 == 0, $"{nameof(bufferLength)} must be evenly divisible by 256");

            var builder = TransportSelector.GetWebHostBuilder()
                          .ConfigureServices(AddTestLogging)
                          .UseKestrel(options =>
            {
                options.Limits.MaxRequestBodySize     = contentLength;
                options.Limits.MinRequestBodyDataRate = null;
            })
                          .UseUrls("http://127.0.0.1:0/")
                          .Configure(app =>
            {
                app.Run(async context =>
                {
                    // Read the full request body
                    long total        = 0;
                    var receivedBytes = new byte[bufferLength];
                    var received      = 0;
                    while ((received = await context.Request.Body.ReadAsync(receivedBytes, 0, receivedBytes.Length)) > 0)
                    {
                        if (checkBytes)
                        {
                            for (var i = 0; i < received; i++)
                            {
                                // Do not use Assert.Equal here, it is to slow for this hot path
                                Assert.True((byte)((total + i) % 256) == receivedBytes[i], "Data received is incorrect");
                            }
                        }

                        total += received;
                    }

                    await context.Response.WriteAsync($"bytesRead: {total.ToString()}");
                });
            });

            using (var host = builder.Build())
            {
                await host.StartAsync();

                using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                {
                    socket.Connect(new IPEndPoint(IPAddress.Loopback, host.GetPort()));
                    socket.Send(Encoding.ASCII.GetBytes("POST / HTTP/1.1\r\nHost: \r\n"));
                    socket.Send(Encoding.ASCII.GetBytes($"Content-Length: {contentLength}\r\n\r\n"));

                    var contentBytes = new byte[bufferLength];

                    if (checkBytes)
                    {
                        for (var i = 0; i < contentBytes.Length; i++)
                        {
                            contentBytes[i] = (byte)i;
                        }
                    }

                    for (var i = 0; i < contentLength / contentBytes.Length; i++)
                    {
                        socket.Send(contentBytes);
                    }

                    using (var stream = new NetworkStream(socket))
                    {
                        await AssertStreamContains(stream, $"bytesRead: {contentLength}");
                    }
                }

                await host.StopAsync();
            }
        }
Example #8
0
        private async Task <IWebHost> StartWebHost(long?maxRequestBufferSize,
                                                   byte[] expectedBody,
                                                   bool useConnectionAdapter,
                                                   TaskCompletionSource <object> startReadingRequestBody,
                                                   TaskCompletionSource <object> clientFinishedSendingRequestBody,
                                                   Func <MemoryPool <byte> > memoryPoolFactory = null)
        {
            var host = TransportSelector.GetWebHostBuilder(memoryPoolFactory)
                       .ConfigureServices(AddTestLogging)
                       .UseKestrel(options =>
            {
                options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
                {
                    if (useConnectionAdapter)
                    {
                        listenOptions.ConnectionAdapters.Add(new PassThroughConnectionAdapter());
                    }
                });

                options.Limits.MaxRequestBufferSize = maxRequestBufferSize;

                if (maxRequestBufferSize.HasValue &&
                    maxRequestBufferSize.Value < options.Limits.MaxRequestLineSize)
                {
                    options.Limits.MaxRequestLineSize = (int)maxRequestBufferSize;
                }

                if (maxRequestBufferSize.HasValue &&
                    maxRequestBufferSize.Value < options.Limits.MaxRequestHeadersTotalSize)
                {
                    options.Limits.MaxRequestHeadersTotalSize = (int)maxRequestBufferSize;
                }

                options.Limits.MinRequestBodyDataRate = null;

                options.Limits.MaxRequestBodySize = _dataLength;
            })
                       .UseContentRoot(Directory.GetCurrentDirectory())
                       .Configure(app => app.Run(async context =>
            {
                await startReadingRequestBody.Task.TimeoutAfter(TimeSpan.FromSeconds(120));

                var buffer    = new byte[expectedBody.Length];
                var bytesRead = 0;
                while (bytesRead < buffer.Length)
                {
                    bytesRead += await context.Request.Body.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
                }

                await clientFinishedSendingRequestBody.Task.TimeoutAfter(TimeSpan.FromSeconds(120));

                // Verify client didn't send extra bytes
                if (await context.Request.Body.ReadAsync(new byte[1], 0, 1) != 0)
                {
                    context.Response.StatusCode = StatusCodes.Status500InternalServerError;
                    await context.Response.WriteAsync("Client sent more bytes than expectedBody.Length");
                    return;
                }

                await context.Response.WriteAsync($"bytesRead: {bytesRead.ToString()}");
            }))
                       .Build();

            await host.StartAsync();

            return(host);
        }