public async Task GetDateHeaderValue_ReturnsUpdatedValueAfterIdle() { var now = DateTimeOffset.UtcNow; var future = now.AddSeconds(10); var systemClock = new MockSystemClock { UtcNow = now }; var timeWithoutRequestsUntilIdle = TimeSpan.FromMilliseconds(250); var timerInterval = TimeSpan.FromMilliseconds(100); var dateHeaderValueManager = new DateHeaderValueManager(systemClock, timeWithoutRequestsUntilIdle, timerInterval); string result1; string result2; try { result1 = dateHeaderValueManager.GetDateHeaderValue(); systemClock.UtcNow = future; // Wait for longer than the idle timeout to ensure the timer is stopped await Task.Delay(TimeSpan.FromSeconds(1)); result2 = dateHeaderValueManager.GetDateHeaderValue(); } finally { dateHeaderValueManager.Dispose(); } Assert.Equal(now.ToString(Constants.RFC1123DateFormat), result1); Assert.Equal(future.ToString(Constants.RFC1123DateFormat), result2); Assert.True(systemClock.UtcNowCalled >= 2); }
public void GetDateHeaderValue_ReturnsCachedValueBetweenTimerTicks() { var now = DateTimeOffset.UtcNow; var future = now.AddSeconds(10); var systemClock = new MockSystemClock { UtcNow = now }; var timeWithoutRequestsUntilIdle = TimeSpan.FromSeconds(1); var timerInterval = TimeSpan.FromSeconds(10); var dateHeaderValueManager = new DateHeaderValueManager(systemClock, timeWithoutRequestsUntilIdle, timerInterval); string result1; string result2; try { result1 = dateHeaderValueManager.GetDateHeaderValue(); systemClock.UtcNow = future; result2 = dateHeaderValueManager.GetDateHeaderValue(); } finally { dateHeaderValueManager.Dispose(); } Assert.Equal(now.ToString(Constants.RFC1123DateFormat), result1); Assert.Equal(now.ToString(Constants.RFC1123DateFormat), result2); Assert.Equal(1, systemClock.UtcNowCalled); }
public void Initialize(DateHeaderValueManager dateValueManager) { ResponseHeaders.SetRawDate( dateValueManager.GetDateHeaderValue(), dateValueManager.GetDateHeaderValueBytes()); ResponseHeaders.SetRawServer("Kestrel", BytesServer); }
public void GetDateHeaderValue_ReturnsUpdatedValueAfterHeartbeat() { var now = DateTimeOffset.UtcNow; var future = now.AddSeconds(10); var systemClock = new MockSystemClock { UtcNow = now }; var dateHeaderValueManager = new DateHeaderValueManager(); dateHeaderValueManager.OnHeartbeat(now); var testKestrelTrace = new KestrelTrace(NullLoggerFactory.Instance); var mockHeartbeatHandler = new Mock <IHeartbeatHandler>(); using (var heartbeat = new Heartbeat(new[] { dateHeaderValueManager, mockHeartbeatHandler.Object }, systemClock, DebuggerWrapper.Singleton, testKestrelTrace)) { heartbeat.OnHeartbeat(); Assert.Equal(now.ToString(Rfc1123DateFormat), dateHeaderValueManager.GetDateHeaderValues().String); // Wait for the next heartbeat before verifying GetDateHeaderValues picks up new time. systemClock.UtcNow = future; heartbeat.OnHeartbeat(); Assert.Equal(future.ToString(Rfc1123DateFormat), dateHeaderValueManager.GetDateHeaderValues().String); Assert.Equal(4, systemClock.UtcNowCalled); } }
private static ServiceContext CreateServiceContext(IOptions <KestrelServerOptions> options, ILoggerFactory loggerFactory) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } var serverOptions = options.Value ?? new KestrelServerOptions(); var logger = loggerFactory.CreateLogger("Microsoft.AspNetCore.Server.Kestrel"); var trace = new KestrelTrace(logger); var connectionManager = new HttpConnectionManager( trace, serverOptions.Limits.MaxConcurrentUpgradedConnections); var systemClock = new SystemClock(); var dateHeaderValueManager = new DateHeaderValueManager(systemClock); var httpHeartbeatManager = new HttpHeartbeatManager(connectionManager); var heartbeat = new Heartbeat( new IHeartbeatHandler[] { dateHeaderValueManager, httpHeartbeatManager }, systemClock, DebuggerWrapper.Singleton, trace); // TODO: This logic will eventually move into the IConnectionHandler<T> and off // the service context once we get to https://github.com/aspnet/KestrelHttpServer/issues/1662 PipeScheduler scheduler = null; switch (serverOptions.ApplicationSchedulingMode) { case SchedulingMode.Default: case SchedulingMode.ThreadPool: scheduler = PipeScheduler.ThreadPool; break; case SchedulingMode.Inline: scheduler = PipeScheduler.Inline; break; default: throw new NotSupportedException(CoreStrings.FormatUnknownTransportMode(serverOptions.ApplicationSchedulingMode)); } return(new ServiceContext { Log = trace, HttpParser = new HttpParser <Http1ParsingHandler>(trace.IsEnabled(LogLevel.Information)), Scheduler = scheduler, SystemClock = systemClock, DateHeaderValueManager = dateHeaderValueManager, ConnectionManager = connectionManager, Heartbeat = heartbeat, ServerOptions = serverOptions, }); }
public void GlobalSetup() { _responseHeaders = new HttpResponseHeaders(); _responseHeadersDict = _responseHeaders; _dateHeaderValueManager = new DateHeaderValueManager(); _dateHeaderValueManager.OnHeartbeat(DateTimeOffset.Now); _writer = new Writer(); }
public void GetDateHeaderValue_ReturnsDateValueInRFC1123Format() { var now = DateTimeOffset.UtcNow; var dateHeaderValueManager = new DateHeaderValueManager(now); Assert.Equal(now.ToString(Rfc1123DateFormat), dateHeaderValueManager.GetDateHeaderValues().String); }
public TestServiceContext() { AppLifetime = new LifetimeNotImplemented(); Log = new TestKestrelTrace(); ThreadPool = new LoggingThreadPool(Log); DateHeaderValueManager = new DateHeaderValueManager(systemClock: new MockSystemClock()); DateHeaderValue = DateHeaderValueManager.GetDateHeaderValues().String; ServerOptions = new KestrelServerOptions { AddServerHeader = false }; ServerOptions.ShutdownTimeout = TimeSpan.FromSeconds(5); }
private static ServiceContext CreateServiceContext(IOptions <KestrelServerOptions> options, ILoggerFactory loggerFactory) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } var serverOptions = options.Value ?? new KestrelServerOptions(); var logger = loggerFactory.CreateLogger("Microsoft.AspNetCore.Server.Kestrel"); var trace = new KestrelTrace(logger); var connectionManager = new FrameConnectionManager( trace, serverOptions.Limits.MaxConcurrentConnections, serverOptions.Limits.MaxConcurrentUpgradedConnections); var systemClock = new SystemClock(); var dateHeaderValueManager = new DateHeaderValueManager(systemClock); // TODO: This logic will eventually move into the IConnectionHandler<T> and off // the service context once we get to https://github.com/aspnet/KestrelHttpServer/issues/1662 IThreadPool threadPool = null; switch (serverOptions.ApplicationSchedulingMode) { case SchedulingMode.Default: case SchedulingMode.ThreadPool: threadPool = new LoggingThreadPool(trace); break; case SchedulingMode.Inline: threadPool = new InlineLoggingThreadPool(trace); break; default: throw new NotSupportedException(CoreStrings.FormatUnknownTransportMode(serverOptions.ApplicationSchedulingMode)); } return(new ServiceContext { Log = trace, HttpParserFactory = frameParser => new HttpParser <FrameAdapter>(frameParser.Frame.ServiceContext.Log.IsEnabled(LogLevel.Information)), ThreadPool = threadPool, SystemClock = systemClock, DateHeaderValueManager = dateHeaderValueManager, ConnectionManager = connectionManager, ServerOptions = serverOptions }); }
public Headers CreateHeaders(DateHeaderValueManager dateValueManager) { Headers headers; if (!_headerPool.TryDequeue(out headers)) { headers = new Headers(); } headers.Initialize(dateValueManager); return(headers); }
private void Initialize(ILoggerFactory loggerFactory, IKestrelTrace kestrelTrace) { LoggerFactory = loggerFactory; Log = kestrelTrace; ThreadPool = new LoggingThreadPool(Log); SystemClock = new MockSystemClock(); DateHeaderValueManager = new DateHeaderValueManager(SystemClock); ConnectionManager = new HttpConnectionManager(Log, ResourceCounter.Unlimited); HttpParser = new HttpParser <Http1ParsingHandler>(Log.IsEnabled(LogLevel.Information)); ServerOptions = new KestrelServerOptions { AddServerHeader = false }; }
public TestServiceContext(ILoggerFactory loggerFactory, IKestrelTrace kestrelTrace) { LoggerFactory = loggerFactory; Log = kestrelTrace; ThreadPool = new LoggingThreadPool(Log); SystemClock = new MockSystemClock(); DateHeaderValueManager = new DateHeaderValueManager(SystemClock); ConnectionManager = new FrameConnectionManager(Log, ResourceCounter.Unlimited, ResourceCounter.Unlimited); HttpParserFactory = frameAdapter => new HttpParser <FrameAdapter>(frameAdapter.Frame.ServiceContext.Log.IsEnabled(LogLevel.Information)); ServerOptions = new KestrelServerOptions { AddServerHeader = false }; }
public void InitializeHeartbeat() { var heartbeatManager = new HeartbeatManager(ConnectionManager); DateHeaderValueManager = new DateHeaderValueManager(); Heartbeat = new Heartbeat( new IHeartbeatHandler[] { DateHeaderValueManager, heartbeatManager }, new SystemClock(), DebuggerWrapper.Singleton, Log); MockSystemClock = null; SystemClock = heartbeatManager; }
public async Task RequestTimesOutWhenNotDrainedWithinDrainTimeoutPeriod() { // This test requires a real clock since we can't control when the drain timeout is set var serviceContext = new TestServiceContext(LoggerFactory); serviceContext.InitializeHeartbeat(); // Ensure there's still a constant date header value. var clock = new MockSystemClock(); var date = new DateHeaderValueManager(); date.OnHeartbeat(clock.UtcNow); serviceContext.DateHeaderValueManager = date; var appRunningEvent = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); using (var server = new TestServer(context => { context.Features.Get <IHttpMinRequestBodyDataRateFeature>().MinDataRate = null; appRunningEvent.SetResult(null); return(Task.CompletedTask); }, serviceContext)) { using (var connection = server.CreateConnection()) { await connection.Send( "POST / HTTP/1.1", "Host:", "Content-Length: 1", "", ""); await appRunningEvent.Task.DefaultTimeout(); // Disconnects after response completes due to the timeout await connection.ReceiveEnd( "HTTP/1.1 200 OK", $"Date: {serviceContext.DateHeaderValue}", "Content-Length: 0", "", ""); } await server.StopAsync(); } Assert.Contains(TestSink.Writes, w => w.EventId.Id == 32 && w.LogLevel == LogLevel.Information); Assert.Contains(TestSink.Writes, w => w.EventId.Id == 33 && w.LogLevel == LogLevel.Information); }
private void Initialize(ILoggerFactory loggerFactory, KestrelTrace kestrelTrace) { LoggerFactory = loggerFactory; Log = kestrelTrace; Scheduler = PipeScheduler.ThreadPool; MockSystemClock = new MockSystemClock(); SystemClock = MockSystemClock; DateHeaderValueManager = new DateHeaderValueManager(); ConnectionManager = new ConnectionManager(Log, ResourceCounter.Unlimited); HttpParser = new HttpParser <Http1ParsingHandler>(Log.IsEnabled(LogLevel.Information)); ServerOptions = new KestrelServerOptions { AddServerHeader = false }; DateHeaderValueManager.OnHeartbeat(SystemClock.UtcNow); }
public void GetDateHeaderValue_ReturnsCachedValueBetweenTimerTicks() { var now = DateTimeOffset.UtcNow; var future = now.AddSeconds(10); var systemClock = new MockSystemClock { UtcNow = now }; var dateHeaderValueManager = new DateHeaderValueManager(now); var testKestrelTrace = new TestKestrelTrace(); using (var heartbeat = new Heartbeat(new IHeartbeatHandler[] { dateHeaderValueManager }, systemClock, DebuggerWrapper.Singleton, testKestrelTrace)) { Assert.Equal(now.ToString(Rfc1123DateFormat), dateHeaderValueManager.GetDateHeaderValues().String); systemClock.UtcNow = future; Assert.Equal(now.ToString(Rfc1123DateFormat), dateHeaderValueManager.GetDateHeaderValues().String); } Assert.Equal(0, systemClock.UtcNowCalled); }
public void GetDateHeaderValue_ReturnsDateValueAfterDisposed() { var now = DateTimeOffset.UtcNow; var future = now.AddSeconds(10); var systemClock = new MockSystemClock { UtcNow = now }; var timeWithoutRequestsUntilIdle = TimeSpan.FromSeconds(1); var timerInterval = TimeSpan.FromSeconds(10); var dateHeaderValueManager = new DateHeaderValueManager(systemClock, timeWithoutRequestsUntilIdle, timerInterval); var result1 = dateHeaderValueManager.GetDateHeaderValue(); dateHeaderValueManager.Dispose(); systemClock.UtcNow = future; var result2 = dateHeaderValueManager.GetDateHeaderValue(); Assert.Equal(now.ToString(Constants.RFC1123DateFormat), result1); Assert.Equal(future.ToString(Constants.RFC1123DateFormat), result2); }
public void GetDateHeaderValue_ReturnsLastDateValueAfterHeartbeatDisposed() { var now = DateTimeOffset.UtcNow; var future = now.AddSeconds(10); var systemClock = new MockSystemClock { UtcNow = now }; var dateHeaderValueManager = new DateHeaderValueManager(now); var testKestrelTrace = new TestKestrelTrace(); using (var heatbeat = new Heartbeat(new IHeartbeatHandler[] { dateHeaderValueManager }, systemClock, DebuggerWrapper.Singleton, testKestrelTrace)) { heatbeat.OnHeartbeat(); Assert.Equal(now.ToString(Rfc1123DateFormat), dateHeaderValueManager.GetDateHeaderValues().String); } systemClock.UtcNow = future; Assert.Equal(now.ToString(Rfc1123DateFormat), dateHeaderValueManager.GetDateHeaderValues().String); }
private static ServiceContext CreateServiceContext(IOptions <KestrelServerOptions> options, ILoggerFactory loggerFactory, DiagnosticSource?diagnosticSource) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } var serverOptions = options.Value ?? new KestrelServerOptions(); var trace = new KestrelTrace(loggerFactory); var connectionManager = new ConnectionManager( trace, serverOptions.Limits.MaxConcurrentUpgradedConnections); var heartbeatManager = new HeartbeatManager(connectionManager); var dateHeaderValueManager = new DateHeaderValueManager(); var heartbeat = new Heartbeat( new IHeartbeatHandler[] { dateHeaderValueManager, heartbeatManager }, new SystemClock(), DebuggerWrapper.Singleton, trace); return(new ServiceContext { Log = trace, Scheduler = PipeScheduler.ThreadPool, HttpParser = new HttpParser <Http1ParsingHandler>(trace.IsEnabled(LogLevel.Information)), SystemClock = heartbeatManager, DateHeaderValueManager = dateHeaderValueManager, ConnectionManager = connectionManager, Heartbeat = heartbeat, ServerOptions = serverOptions, DiagnosticSource = diagnosticSource }); }
public static ServiceContext CreateServiceContext( KestrelServerOptions serverOptions, IHttpParser <Http1ParsingHandler> httpParser = null, PipeScheduler scheduler = null, ISystemClock systemClock = null, DateHeaderValueManager dateHeaderValueManager = null, ConnectionManager connectionManager = null, Heartbeat heartbeat = null) { var context = new ServiceContext { Log = new KestrelTrace(NullLoggerFactory.Instance), Scheduler = scheduler, HttpParser = httpParser, SystemClock = systemClock, DateHeaderValueManager = dateHeaderValueManager, ConnectionManager = connectionManager, Heartbeat = heartbeat, ServerOptions = serverOptions }; return(context); }
public void GetDateHeaderValue_ReturnsDateValueInRFC1123Format() { var now = DateTimeOffset.UtcNow; var systemClock = new MockSystemClock { UtcNow = now }; var timeWithoutRequestsUntilIdle = TimeSpan.FromSeconds(1); var timerInterval = TimeSpan.FromSeconds(10); var dateHeaderValueManager = new DateHeaderValueManager(systemClock, timeWithoutRequestsUntilIdle, timerInterval); string result; try { result = dateHeaderValueManager.GetDateHeaderValue(); } finally { dateHeaderValueManager.Dispose(); } Assert.Equal(now.ToString(Constants.RFC1123DateFormat), result); }
public async Task ClientCanReceiveFullConnectionCloseResponseWithoutErrorAtALowDataRate() { var chunkSize = 64 * 128 * 1024; var chunkCount = 4; var chunkData = new byte[chunkSize]; var requestAborted = false; var appFuncCompleted = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); var mockKestrelTrace = new Mock <IKestrelTrace>(); var testContext = new TestServiceContext(LoggerFactory, mockKestrelTrace.Object) { ServerOptions = { Limits = { MinResponseDataRate = new MinDataRate(bytesPerSecond: 240, gracePeriod: TimeSpan.FromSeconds(2)) } } }; testContext.InitializeHeartbeat(); var dateHeaderValueManager = new DateHeaderValueManager(); dateHeaderValueManager.OnHeartbeat(DateTimeOffset.MinValue); testContext.DateHeaderValueManager = dateHeaderValueManager; var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)); async Task App(HttpContext context) { context.RequestAborted.Register(() => { requestAborted = true; }); for (var i = 0; i < chunkCount; i++) { await context.Response.BodyWriter.WriteAsync(new Memory <byte>(chunkData, 0, chunkData.Length), context.RequestAborted); } appFuncCompleted.SetResult(null); } using (var server = new TestServer(App, testContext, listenOptions)) { using (var connection = server.CreateConnection()) { // Close the connection with the last request so AssertStreamCompleted actually completes. await connection.Send( "GET / HTTP/1.1", "Host:", "Connection: close", "", ""); await connection.Receive( "HTTP/1.1 200 OK", "Connection: close", $"Date: {dateHeaderValueManager.GetDateHeaderValues().String}"); // Make sure consuming a single chunk exceeds the 2 second timeout. var targetBytesPerSecond = chunkSize / 4; // expectedBytes was determined by manual testing. A constant Date header is used, so this shouldn't change unless // the response header writing logic or response body chunking logic itself changes. await AssertStreamCompletedAtTargetRate(connection.Stream, expectedBytes : 33_553_556, targetBytesPerSecond); await appFuncCompleted.Task.DefaultTimeout(); } await server.StopAsync(); } mockKestrelTrace.Verify(t => t.ResponseMinimumDataRateNotSatisfied(It.IsAny <string>(), It.IsAny <string>()), Times.Never()); mockKestrelTrace.Verify(t => t.ConnectionStop(It.IsAny <string>()), Times.Once()); Assert.False(requestAborted); }
public async Task ConnectionNotClosedWhenClientSatisfiesMinimumDataRateGivenLargeResponseHeaders() { var headerSize = 1024 * 1024; // 1 MB for each header value var headerCount = 64; // 64 MB of headers per response var requestCount = 4; // Minimum of 256 MB of total response headers var headerValue = new string('a', headerSize); var headerStringValues = new StringValues(Enumerable.Repeat(headerValue, headerCount).ToArray()); var requestAborted = false; var mockKestrelTrace = new Mock <IKestrelTrace>(); var testContext = new TestServiceContext(LoggerFactory, mockKestrelTrace.Object) { ServerOptions = { Limits = { MinResponseDataRate = new MinDataRate(bytesPerSecond: 240, gracePeriod: TimeSpan.FromSeconds(2)) } } }; testContext.InitializeHeartbeat(); var dateHeaderValueManager = new DateHeaderValueManager(); dateHeaderValueManager.OnHeartbeat(DateTimeOffset.MinValue); testContext.DateHeaderValueManager = dateHeaderValueManager; var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)); async Task App(HttpContext context) { context.RequestAborted.Register(() => { requestAborted = true; }); context.Response.Headers[$"X-Custom-Header"] = headerStringValues; context.Response.ContentLength = 0; await context.Response.BodyWriter.FlushAsync(); } using (var server = new TestServer(App, testContext, listenOptions)) { using (var connection = server.CreateConnection()) { for (var i = 0; i < requestCount - 1; i++) { await connection.Send( "GET / HTTP/1.1", "Host:", "", ""); } await connection.Send( "GET / HTTP/1.1", "Host:", "", ""); await connection.Receive( "HTTP/1.1 200 OK", $"Date: {dateHeaderValueManager.GetDateHeaderValues().String}"); var minResponseSize = headerSize * headerCount; var minTotalOutputSize = requestCount * minResponseSize; // Make sure consuming a single set of response headers exceeds the 2 second timeout. var targetBytesPerSecond = minResponseSize / 4; // expectedBytes was determined by manual testing. A constant Date header is used, so this shouldn't change unless // the response header writing logic itself changes. await AssertBytesReceivedAtTargetRate(connection.Stream, expectedBytes : 268_439_596, targetBytesPerSecond); connection.ShutdownSend(); await connection.WaitForConnectionClose(); } await server.StopAsync(); } mockKestrelTrace.Verify(t => t.ResponseMinimumDataRateNotSatisfied(It.IsAny <string>(), It.IsAny <string>()), Times.Never()); mockKestrelTrace.Verify(t => t.ConnectionStop(It.IsAny <string>()), Times.Once()); Assert.False(requestAborted); }
public async Task ConnectionNotClosedWhenClientSatisfiesMinimumDataRateGivenLargeResponseChunks() { var chunkSize = 64 * 128 * 1024; var chunkCount = 4; var chunkData = new byte[chunkSize]; var requestAborted = false; var appFuncCompleted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var testContext = new TestServiceContext(LoggerFactory) { ServerOptions = { Limits = { MinResponseDataRate = new MinDataRate(bytesPerSecond: 240, gracePeriod: TimeSpan.FromSeconds(2)) } } }; testContext.InitializeHeartbeat(); var dateHeaderValueManager = new DateHeaderValueManager(); dateHeaderValueManager.OnHeartbeat(DateTimeOffset.MinValue); testContext.DateHeaderValueManager = dateHeaderValueManager; var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)); async Task App(HttpContext context) { context.RequestAborted.Register(() => { requestAborted = true; }); for (var i = 0; i < chunkCount; i++) { await context.Response.BodyWriter.WriteAsync(new Memory <byte>(chunkData, 0, chunkData.Length), context.RequestAborted); } appFuncCompleted.SetResult(); } await using (var server = new TestServer(App, testContext, listenOptions)) { using (var connection = server.CreateConnection()) { // Close the connection with the last request so AssertStreamCompleted actually completes. await connection.Send( "GET / HTTP/1.1", "Host:", "", ""); await connection.Receive( "HTTP/1.1 200 OK", $"Date: {dateHeaderValueManager.GetDateHeaderValues().String}"); // Make sure consuming a single chunk exceeds the 2 second timeout. var targetBytesPerSecond = chunkSize / 4; // expectedBytes was determined by manual testing. A constant Date header is used, so this shouldn't change unless // the response header writing logic or response body chunking logic itself changes. await AssertBytesReceivedAtTargetRate(connection.Stream, expectedBytes : 33_553_537, targetBytesPerSecond); await appFuncCompleted.Task.DefaultTimeout(); connection.ShutdownSend(); await connection.WaitForConnectionClose(); } } Assert.Equal(0, TestSink.Writes.Count(w => w.EventId.Name == "ResponseMinimumDataRateNotSatisfied")); Assert.Equal(1, TestSink.Writes.Count(w => w.EventId.Name == "ConnectionStop")); Assert.False(requestAborted); }
public IDisposable Start(IFeatureCollection serverFeatures, Func <IFeatureCollection, Task> application) { var disposables = new Stack <IDisposable>(); var disposer = new Disposable(() => { foreach (var disposable in disposables) { disposable.Dispose(); } }); try { var information = (KestrelServerInformation)serverFeatures.Get <IKestrelServerInformation>(); var dateHeaderValueManager = new DateHeaderValueManager(); var engine = new KestrelEngine(_libraryManager, new ServiceContext { AppShutdown = _appShutdownService, Log = new KestrelTrace(_logger), DateHeaderValueManager = dateHeaderValueManager }); disposables.Push(engine); disposables.Push(dateHeaderValueManager); if (information.ThreadCount < 0) { throw new ArgumentOutOfRangeException(nameof(information.ThreadCount), information.ThreadCount, "ThreadCount cannot be negative"); } engine.Start(information.ThreadCount == 0 ? 1 : information.ThreadCount); bool atLeastOneListener = false; foreach (var address in information.Addresses) { var parsedAddress = ServerAddress.FromUrl(address); if (parsedAddress == null) { throw new FormatException("Unrecognized listening address: " + address); } else { atLeastOneListener = true; disposables.Push(engine.CreateServer( parsedAddress.Scheme, parsedAddress.Host, parsedAddress.Port, async frame => { var request = new ServerRequest(frame); await application.Invoke(request.Features).ConfigureAwait(false); })); } } if (!atLeastOneListener) { throw new InvalidOperationException("No recognized listening addresses were configured."); } return(disposer); } catch { disposer.Dispose(); throw; } }
public void Start <TContext>(IHttpApplication <TContext> application) { if (_disposables != null) { // The server has already started and/or has not been cleaned up yet throw new InvalidOperationException("Server has already started."); } _disposables = new Stack <IDisposable>(); try { var componentFactory = Features.Get <IHttpComponentFactory>(); var dateHeaderValueManager = new DateHeaderValueManager(); var trace = new KestrelTrace(_logger); var engine = new KestrelEngine(new ServiceContext { FrameFactory = context => { return(new Frame <TContext>(application, context)); }, AppLifetime = _applicationLifetime, Log = trace, ThreadPool = new LoggingThreadPool(trace), DateHeaderValueManager = dateHeaderValueManager, ServerOptions = Options, HttpComponentFactory = componentFactory }); _disposables.Push(engine); _disposables.Push(dateHeaderValueManager); var threadCount = Options.ThreadCount; if (threadCount <= 0) { throw new ArgumentOutOfRangeException(nameof(threadCount), threadCount, "ThreadCount must be positive."); } engine.Start(threadCount); var atLeastOneListener = false; foreach (var address in _serverAddresses.Addresses) { var parsedAddress = ServerAddress.FromUrl(address); if (parsedAddress == null) { throw new FormatException("Unrecognized listening address: " + address); } else { atLeastOneListener = true; _disposables.Push(engine.CreateServer( parsedAddress)); } } if (!atLeastOneListener) { throw new InvalidOperationException("No recognized listening addresses were configured."); } } catch { Dispose(); throw; } }
public void Start <TContext>(IHttpApplication <TContext> application) { if (_disposables != null) { // The server has already started and/or has not been cleaned up yet throw new InvalidOperationException("Server has already started."); } _disposables = new Stack <IDisposable>(); try { var dateHeaderValueManager = new DateHeaderValueManager(); var trace = new KestrelTrace(_logger); var engine = new KestrelEngine(new ServiceContext { FrameFactory = context => { return(new Frame <TContext>(application, context)); }, AppLifetime = _applicationLifetime, Log = trace, ThreadPool = new LoggingThreadPool(trace), DateHeaderValueManager = dateHeaderValueManager, ServerOptions = Options }); _disposables.Push(engine); _disposables.Push(dateHeaderValueManager); var threadCount = Options.ThreadCount; if (threadCount <= 0) { throw new ArgumentOutOfRangeException(nameof(threadCount), threadCount, "ThreadCount must be positive."); } if (!Constants.ECONNRESET.HasValue) { _logger.LogWarning("Unable to determine ECONNRESET value on this platform."); } if (!Constants.EADDRINUSE.HasValue) { _logger.LogWarning("Unable to determine EADDRINUSE value on this platform."); } engine.Start(threadCount); var atLeastOneListener = false; foreach (var address in _serverAddresses.Addresses.ToArray()) { var parsedAddress = ServerAddress.FromUrl(address); atLeastOneListener = true; if (!parsedAddress.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase)) { _disposables.Push(engine.CreateServer( parsedAddress)); } else { if (parsedAddress.Port == 0) { throw new InvalidOperationException("Dynamic port binding is not supported when binding to localhost. You must either bind to 127.0.0.1:0 or [::1]:0, or both."); } var ipv4Address = parsedAddress.WithHost("127.0.0.1"); var exceptions = new List <UvException>(); try { _disposables.Push(engine.CreateServer(ipv4Address)); } catch (AggregateException ex) { var uvException = ex.InnerException as UvException; if (uvException != null && uvException.StatusCode != Constants.EADDRINUSE) { _logger.LogWarning(0, ex, $"Unable to bind to {parsedAddress.ToString()} on the IPv4 loopback interface."); exceptions.Add(uvException); } else { throw; } } var ipv6Address = parsedAddress.WithHost("[::1]"); try { _disposables.Push(engine.CreateServer(ipv6Address)); } catch (AggregateException ex) { var uvException = ex.InnerException as UvException; if (uvException != null && uvException.StatusCode != Constants.EADDRINUSE) { _logger.LogWarning(0, ex, $"Unable to bind to {parsedAddress.ToString()} on the IPv6 loopback interface."); exceptions.Add(uvException); } else { throw; } } if (exceptions.Count == 2) { var ex = new AggregateException(exceptions); _logger.LogError(0, ex, $"Unable to bind to {parsedAddress.ToString()} on any loopback interface."); throw ex; } } // If requested port was "0", replace with assigned dynamic port. _serverAddresses.Addresses.Remove(address); _serverAddresses.Addresses.Add(parsedAddress.ToString()); } if (!atLeastOneListener) { throw new InvalidOperationException("No recognized listening addresses were configured."); } } catch { Dispose(); throw; } }