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(); } }
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(); } }
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(); } }
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); } } }
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(); } }
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."); } }
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(); } }
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); }