public async Task DefaultAddressBinderWithoutDevCertButHttpsConfiguredBindsToHttpsPorts() { var x509Certificate2 = TestResources.GetTestCertificate(); var logger = new MockLogger(); var addresses = new ServerAddressesFeature(); var services = new ServiceCollection(); services.AddLogging(); var options = new KestrelServerOptions() { // This stops the dev cert from being loaded IsDevCertLoaded = true, ApplicationServices = services.BuildServiceProvider() }; options.ConfigureEndpointDefaults(e => { if (e.IPEndPoint.Port == 5001) { e.UseHttps(new HttpsConnectionAdapterOptions { ServerCertificate = x509Certificate2 }); } }); var endpoints = new List <ListenOptions>(); await AddressBinder.BindAsync(addresses, options, logger, listenOptions => { endpoints.Add(listenOptions); return(Task.CompletedTask); }); Assert.Contains(endpoints, e => e.IPEndPoint.Port == 5000 && !e.IsTls); Assert.Contains(endpoints, e => e.IPEndPoint.Port == 5001 && e.IsTls); }
private async Task BindAsync(CancellationToken cancellationToken) { await _bindSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try { if (_stopping == 1) { throw new InvalidOperationException("Kestrel has already been stopped."); } IChangeToken?reloadToken = null; _serverAddresses.InternalCollection.PreventPublicMutation(); if (Options.ConfigurationLoader?.ReloadOnChange == true && (!_serverAddresses.PreferHostingUrls || _serverAddresses.InternalCollection.Count == 0)) { reloadToken = Options.ConfigurationLoader.Configuration.GetReloadToken(); } Options.ConfigurationLoader?.Load(); await AddressBinder.BindAsync(Options.ListenOptions, AddressBindContext !, cancellationToken).ConfigureAwait(false); _configChangedRegistration = reloadToken?.RegisterChangeCallback(TriggerRebind, this); } finally { _bindSemaphore.Release(); } }
public void LogsInformationWhenKestrelAddressesAreOverridden() { var logger = new TestApplicationErrorLogger(); var overriddenAddress = "http://localhost:5000"; var addresses = new ServerAddressesFeature(); addresses.InternalCollection.Add(overriddenAddress); var options = new KestrelServerOptions(); options.ListenAnyIP(8080); var addressBindContext = TestContextFactory.CreateAddressBindContext( addresses, options, logger, endpoint => Task.CompletedTask); addressBindContext.ServerAddressesFeature.PreferHostingUrls = true; var bindTask = AddressBinder.BindAsync(options.ListenOptions, addressBindContext, CancellationToken.None); Assert.True(bindTask.IsCompletedSuccessfully); var log = Assert.Single(logger.Messages); Assert.Equal(LogLevel.Information, log.LogLevel); Assert.Equal(CoreStrings.FormatOverridingWithPreferHostingUrls(nameof(addressBindContext.ServerAddressesFeature.PreferHostingUrls), overriddenAddress), log.Message); }
public async Task FallbackToIPv4WhenIPv6AnyBindFails(string address) { var logger = new MockLogger(); var addresses = new ServerAddressesFeature(); addresses.Addresses.Add(address); var options = new KestrelServerOptions(); var ipV6Attempt = false; var ipV4Attempt = false; await AddressBinder.BindAsync(addresses, options, logger, endpoint => { if (endpoint.IPEndPoint.Address == IPAddress.IPv6Any) { ipV6Attempt = true; throw new InvalidOperationException("EAFNOSUPPORT"); } if (endpoint.IPEndPoint.Address == IPAddress.Any) { ipV4Attempt = true; } return(Task.CompletedTask); }); Assert.True(ipV4Attempt, "Should have attempted to bind to IPAddress.Any"); Assert.True(ipV6Attempt, "Should have attempted to bind to IPAddress.IPv6Any"); Assert.Contains(logger.Messages, f => f.Equals(CoreStrings.FormatFallbackToIPv4Any(80))); }
public async Task DefaultAddressBinderBindsToHttpPort5000() { var logger = new MockLogger(); var addresses = new ServerAddressesFeature(); var services = new ServiceCollection(); services.AddLogging(); var options = new KestrelServerOptions() { ApplicationServices = services.BuildServiceProvider() }; var endpoints = new List <ListenOptions>(); var addressBindContext = TestContextFactory.CreateAddressBindContext( addresses, options, logger, listenOptions => { endpoints.Add(listenOptions); return(Task.CompletedTask); }); await AddressBinder.BindAsync(options.ListenOptions, addressBindContext, CancellationToken.None); Assert.Contains(endpoints, e => e.IPEndPoint.Port == 5000 && !e.IsTls); }
public async Task WrapsAddressInUseExceptionAsIOException() { var addresses = new ServerAddressesFeature(); addresses.Addresses.Add("http://localhost:5000"); var options = new KestrelServerOptions(); await Assert.ThrowsAsync <IOException>(() => AddressBinder.BindAsync(addresses, options, NullLogger.Instance, endpoint => throw new AddressInUseException("already in use"))); }
public async Task StartAsync <TContext>(IHttpApplication <TContext> application, CancellationToken cancellationToken) { try { if (!BitConverter.IsLittleEndian) { throw new PlatformNotSupportedException(CoreStrings.BigEndianNotSupported); } ValidateOptions(); if (_hasStarted) { // The server has already started and/or has not been cleaned up yet throw new InvalidOperationException(CoreStrings.ServerAlreadyStarted); } _hasStarted = true; ServiceContext.Heartbeat?.Start(); async Task OnBind(ListenOptions endpoint) { // Add the HTTP middleware as the terminal connection middleware endpoint.UseHttpServer(endpoint.ConnectionAdapters, ServiceContext, application, endpoint.Protocols); var connectionDelegate = endpoint.Build(); // Add the connection limit middleware if (Options.Limits.MaxConcurrentConnections.HasValue) { connectionDelegate = new ConnectionLimitMiddleware(connectionDelegate, Options.Limits.MaxConcurrentConnections.Value, Trace).OnConnectionAsync; } var connectionDispatcher = new ConnectionDispatcher(ServiceContext, connectionDelegate); var transport = _transportFactory.Create(endpoint, connectionDispatcher); _transports.Add(transport); await transport.BindAsync().ConfigureAwait(false); } await AddressBinder.BindAsync(_serverAddresses, Options, Trace, OnBind).ConfigureAwait(false); } catch (Exception ex) { Trace.LogCritical(0, ex, "Unable to start Kestrel."); Dispose(); throw; } }
public async Task WrapsAddressInUseExceptionAsIOException() { var addresses = new ServerAddressesFeature(); addresses.InternalCollection.Add("http://localhost:5000"); var options = new KestrelServerOptions(); var addressBindContext = TestContextFactory.CreateAddressBindContext( addresses, options, NullLogger.Instance, endpoint => throw new AddressInUseException("already in use")); await Assert.ThrowsAsync <IOException>(() => AddressBinder.BindAsync(options.ListenOptions, addressBindContext, CancellationToken.None)); }
public async Task WrapsAddressInUseExceptionAsIOException() { var addresses = new ServerAddressesFeature(); addresses.InternalCollection.Add("http://localhost:5000"); var options = new KestrelServerOptions(); var addressBindContext = new AddressBindContext { ServerAddressesFeature = addresses, ServerOptions = options, Logger = NullLogger.Instance, CreateBinding = endpoint => throw new AddressInUseException("already in use"), }; await Assert.ThrowsAsync <IOException>(() => AddressBinder.BindAsync(options.ListenOptions, addressBindContext)); }
public async Task StartAsync(CancellationToken cancellationToken) { try { if (!BitConverter.IsLittleEndian) { throw new PlatformNotSupportedException("Does not support big-endian architectures."); } if (_hasStarted) { // The server has already started and/or has not been cleaned up yet throw new InvalidOperationException("Server has already started."); } _hasStarted = true; _heartbeat.Start(); async Task OnBind(ListenOptions endpoint) { var connectionDelegate = endpoint.Build(); // Add the connection limit middleware if (Options.Limits.MaxConcurrentConnections.HasValue) { connectionDelegate = new ConnectionLimitMiddleware(connectionDelegate, Options.Limits.MaxConcurrentConnections.Value, Trace).OnConnectionAsync; } var connectionDispatcher = new ConnectionDispatcher(ServiceContext, connectionDelegate); var transport = _transportFactory.Create(endpoint, connectionDispatcher); _transports.Add(transport); await transport.BindAsync().ConfigureAwait(false); } await AddressBinder.BindAsync(_serverAddresses, Options, Trace, OnBind).ConfigureAwait(false); } catch (Exception ex) { Trace.LogCritical(0, ex, "Unable to start Kestrel."); Dispose(); throw; } }
public async Task FlowsCancellationTokenToCreateBinddingCallback() { var addresses = new ServerAddressesFeature(); addresses.InternalCollection.Add("http://localhost:5000"); var options = new KestrelServerOptions(); var addressBindContext = TestContextFactory.CreateAddressBindContext( addresses, options, NullLogger.Instance, (endpoint, cancellationToken) => { cancellationToken.ThrowIfCancellationRequested(); return(Task.CompletedTask); }); await Assert.ThrowsAsync <OperationCanceledException>(() => AddressBinder.BindAsync(options.ListenOptions, addressBindContext, new CancellationToken(true))); }
public async Task DefaultsToIPv6AnyOnInvalidIPAddress(string host) { var addresses = new ServerAddressesFeature(); addresses.Addresses.Add($"http://{host}"); var options = new List <ListenOptions>(); var tcs = new TaskCompletionSource <ListenOptions>(); await AddressBinder.BindAsync(addresses, options, NullLogger.Instance, endpoint => { tcs.TrySetResult(endpoint); return(Task.CompletedTask); }); var result = await tcs.Task; Assert.Equal(IPAddress.IPv6Any, result.IPEndPoint.Address); }
public async Task StartAsync <TContext>(IHttpApplication <TContext> application, CancellationToken cancellationToken) { try { if (!BitConverter.IsLittleEndian) { throw new PlatformNotSupportedException(CoreStrings.BigEndianNotSupported); } ValidateOptions(); if (_hasStarted) { // The server has already started and/or has not been cleaned up yet throw new InvalidOperationException(CoreStrings.ServerAlreadyStarted); } _hasStarted = true; _heartbeat.Start(); async Task OnBind(ListenOptions endpoint) { var connectionHandler = new ConnectionHandler <TContext>(endpoint, ServiceContext, application); var transport = _transportFactory.Create(endpoint, connectionHandler); _transports.Add(transport); await transport.BindAsync().ConfigureAwait(false); } await AddressBinder.BindAsync(_serverAddresses, Options.ListenOptions, Trace, OnBind).ConfigureAwait(false); } catch (Exception ex) { Trace.LogCritical(0, ex, "Unable to start Kestrel."); Dispose(); throw; } }