Esempio n. 1
0
        public async Task ImmediateShutdownDuringOnConnectionAsyncDoesNotCrash()
        {
            var tcs           = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));

            listenOptions.Use(next =>
            {
                return(async context =>
                {
                    await tcs.Task;
                    await next(context);
                });
            });

            var serviceContext = new TestServiceContext(LoggerFactory);

            await using (var server = new TestServer(TestApp.EchoApp, serviceContext, listenOptions))
            {
                Task stopTask;

                using (var connection = server.CreateConnection())
                {
                    stopTask = server.StopAsync();

                    tcs.TrySetResult();
                }

                await stopTask;
            }
        }
Esempio n. 2
0
        public async Task ThrowingSynchronousConnectionMiddlewareDoesNotCrashServer(RequestDelegate requestDelegate)
        {
            var connectionId  = "";
            var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));

            listenOptions.Use(next => context =>
            {
                connectionId = context.ConnectionId;
                throw new InvalidOperationException();
            });

            var serviceContext = new TestServiceContext(LoggerFactory);

            await using (var server = new TestServer(requestDelegate, serviceContext, listenOptions))
            {
                using (var connection = server.CreateConnection())
                {
                    await connection.Send(
                        "POST / HTTP/1.0",
                        "Content-Length: 1000",
                        "\r\n");

                    await connection.WaitForConnectionClose();
                }
            }

            Assert.Contains(LogMessages, m => m.Message.Contains("Unhandled exception while processing " + connectionId + "."));
        }
Esempio n. 3
0
        public async Task CanReadAndWriteWithRewritingConnectionAdapter(RequestDelegate requestDelegate)
        {
            RewritingConnectionMiddleware middleware = null;

            var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));

            listenOptions.Use(next =>
            {
                middleware = new RewritingConnectionMiddleware(next);
                return(middleware.OnConnectionAsync);
            });

            var serviceContext = new TestServiceContext(LoggerFactory);

            var sendString = "POST / HTTP/1.0\r\nContent-Length: 12\r\n\r\nHello World?";

            await using (var server = new TestServer(requestDelegate, serviceContext, listenOptions))
            {
                using (var connection = server.CreateConnection())
                {
                    // "?" changes to "!"
                    await connection.Send(sendString);

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Connection: close",
                        $"Date: {serviceContext.DateHeaderValue}",
                        "",
                        "Hello World!");
                }
            }

            Assert.Equal(sendString.Length, middleware.BytesRead);
        }
Esempio n. 4
0
        public async Task ImmediateShutdownAfterOnConnectionAsyncDoesNotCrash(RequestDelegate requestDelegate)
        {
            var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));

            listenOptions.Use(next => new AsyncConnectionMiddleware(next).OnConnectionAsync);

            var serviceContext = new TestServiceContext(LoggerFactory);

            ThrowOnUngracefulShutdown = false;

            var stopTask = Task.CompletedTask;

            await using (var server = new TestServer(requestDelegate, serviceContext, listenOptions))
                using (var shutdownCts = new CancellationTokenSource(TestConstants.DefaultTimeout))
                {
                    using (var connection = server.CreateConnection())
                    {
                        // We assume all CI servers are really slow, so we use a 30 second default test timeout
                        // instead of the 5 second default production timeout. If this test is still flaky,
                        // *then* we can consider collecting and investigating memory dumps.
                        stopTask = server.StopAsync(shutdownCts.Token);
                    }

                    await stopTask;
                }
        }
        public async Task DisposeAsyncAfterReplacingTransportClosesConnection()
        {
            var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));

            var connectionCloseTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var mockDuplexPipe     = new MockDuplexPipe();

            listenOptions.Use(next =>
            {
                return(async context =>
                {
                    context.Transport = mockDuplexPipe;
                    await context.DisposeAsync();
                    await connectionCloseTcs.Task;
                });
            });

            var serviceContext = new TestServiceContext(LoggerFactory);

            await using (var server = new TestServer(TestApp.EmptyApp, serviceContext, listenOptions))
            {
                using (var connection = server.CreateConnection())
                {
                    await connection.WaitForConnectionClose();

                    connectionCloseTcs.SetResult();
                }
            }

            Assert.False(mockDuplexPipe.WasCompleted);
        }
Esempio n. 6
0
    /// <summary>
    /// Configure Kestrel to use HTTPS. This does not use default certificates or other defaults specified via config or
    /// <see cref="KestrelServerOptions.ConfigureHttpsDefaults(Action{HttpsConnectionAdapterOptions})"/>.
    /// </summary>
    /// <param name="listenOptions">The <see cref="ListenOptions"/> to configure.</param>
    /// <param name="callbackOptions">Options for a per connection callback.</param>
    /// <returns>The <see cref="ListenOptions"/>.</returns>
    public static ListenOptions UseHttps(this ListenOptions listenOptions, TlsHandshakeCallbackOptions callbackOptions)
    {
        if (callbackOptions is null)
        {
            throw new ArgumentNullException(nameof(callbackOptions));
        }

        if (callbackOptions.OnConnection is null)
        {
            throw new ArgumentException($"{nameof(TlsHandshakeCallbackOptions.OnConnection)} must not be null.");
        }

        var loggerFactory = listenOptions.KestrelServerOptions?.ApplicationServices.GetRequiredService <ILoggerFactory>() ?? NullLoggerFactory.Instance;

        listenOptions.IsTls = true;
        listenOptions.HttpsCallbackOptions = callbackOptions;

        listenOptions.Use(next =>
        {
            // Set the list of protocols from listen options.
            // Set it inside Use delegate so Protocols and UseHttps can be called out of order.
            callbackOptions.HttpProtocols = listenOptions.Protocols;

            var middleware = new HttpsConnectionMiddleware(next, callbackOptions, loggerFactory);
            return(middleware.OnConnectionAsync);
        });

        return(listenOptions);
    }
Esempio n. 7
0
        /// <summary>
        /// Configure Kestrel to use HTTPS. This does not use default certificates or other defaults specified via config or
        /// <see cref="KestrelServerOptions.ConfigureHttpsDefaults(Action{HttpsConnectionAdapterOptions})"/>.
        /// </summary>
        /// <param name="listenOptions">The <see cref="ListenOptions"/> to configure.</param>
        /// <param name="callbackOptions">Options for a per connection callback.</param>
        /// <returns>The <see cref="ListenOptions"/>.</returns>
        public static ListenOptions UseHttps(this ListenOptions listenOptions, TlsHandshakeCallbackOptions callbackOptions)
        {
            if (callbackOptions is null)
            {
                throw new ArgumentNullException(nameof(callbackOptions));
            }

            if (callbackOptions.OnConnection is null)
            {
                throw new ArgumentException($"{nameof(TlsHandshakeCallbackOptions.OnConnection)} must not be null.");
            }

            if (listenOptions.Protocols.HasFlag(HttpProtocols.Http3))
            {
                throw new NotSupportedException($"{nameof(UseHttps)} with {nameof(TlsHandshakeCallbackOptions)} is not supported with HTTP/3.");
            }

            var loggerFactory = listenOptions.KestrelServerOptions?.ApplicationServices.GetRequiredService <ILoggerFactory>() ?? NullLoggerFactory.Instance;

            listenOptions.IsTls = true;
            listenOptions.Use(next =>
            {
                // Set the list of protocols from listen options
                callbackOptions.HttpProtocols = listenOptions.Protocols;
                var middleware = new HttpsConnectionMiddleware(next, callbackOptions, loggerFactory);
                return(middleware.OnConnectionAsync);
            });

            return(listenOptions);
        }
        public async Task CanReadAndWriteWithAsyncConnectionMiddleware(RequestDelegate requestDelegate)
        {
            var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));

            listenOptions.Use(next => new AsyncConnectionMiddleware(next).OnConnectionAsync);

            var serviceContext = new TestServiceContext(LoggerFactory);

            await using (var server = new TestServer(requestDelegate, serviceContext, listenOptions))
            {
                using (var connection = server.CreateConnection())
                {
                    await connection.Send(
                        "POST / HTTP/1.0",
                        "Content-Length: 12",
                        "",
                        "Hello World?");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Connection: close",
                        $"Date: {serviceContext.DateHeaderValue}",
                        "",
                        "Hello World!");
                }
            }
        }
        /// <summary>
        /// Emits verbose logs for bytes read from and written to the connection.
        /// </summary>
        /// <returns>
        /// The <see cref="ListenOptions"/>.
        /// </returns>
        public static ListenOptions UseConnectionLogging(this ListenOptions listenOptions, string loggerName)
        {
            var loggerFactory = listenOptions.KestrelServerOptions.ApplicationServices.GetRequiredService <ILoggerFactory>();
            var logger        = loggerName == null?loggerFactory.CreateLogger <LoggingConnectionMiddleware>() : loggerFactory.CreateLogger(loggerName);

            listenOptions.Use(next => new LoggingConnectionMiddleware(next, logger).OnConnectionAsync);
            return(listenOptions);
        }
Esempio n. 10
0
 public static ListenOptions UseWindowsAuthentication(this ListenOptions options)
 {
     options.Use(next =>
     {
         var middleware = new AuthenticationConnectionMiddleware(next);
         return(middleware.OnConnectedAsync);
     });
     return(options);
 }
Esempio n. 11
0
        /// <summary>
        /// Configure Kestrel to use HTTPS.
        /// </summary>
        /// <param name="listenOptions">The <see cref="ListenOptions"/> to configure.</param>
        /// <param name="httpsOptionsCallback">Callback to configure HTTPS options.</param>
        /// <param name="state">State for the <paramref name="httpsOptionsCallback"/>.</param>
        /// <param name="handshakeTimeout">Specifies the maximum amount of time allowed for the TLS/SSL handshake. This must be positive and finite.</param>
        /// <returns>The <see cref="ListenOptions"/>.</returns>
        internal static ListenOptions UseHttps(this ListenOptions listenOptions, HttpsOptionsCallback httpsOptionsCallback, object state, TimeSpan handshakeTimeout)
        {
            var loggerFactory = listenOptions.KestrelServerOptions?.ApplicationServices.GetRequiredService <ILoggerFactory>() ?? NullLoggerFactory.Instance;

            listenOptions.IsTls = true;
            listenOptions.Use(next =>
            {
                var middleware = new HttpsConnectionMiddleware(next, httpsOptionsCallback, state, handshakeTimeout, loggerFactory);
                return(middleware.OnConnectionAsync);
            });

            return(listenOptions);
        }
Esempio n. 12
0
        private TestServer CreateServerWithMaxConnections(RequestDelegate app, ResourceCounter concurrentConnectionCounter)
        {
            var serviceContext = new TestServiceContext(LoggerFactory);
            var listenOptions  = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));

            listenOptions.Use(next =>
            {
                var middleware = new ConnectionLimitMiddleware(next, concurrentConnectionCounter, serviceContext.Log);
                return(middleware.OnConnectionAsync);
            });

            return(new TestServer(app, serviceContext, listenOptions));
        }
        /// <summary>
        /// Configure Kestrel to use HTTPS.
        /// </summary>
        /// <param name="listenOptions">The <see cref="ListenOptions"/> to configure.</param>
        /// <param name="httpsOptions">Options to configure HTTPS.</param>
        /// <returns>The <see cref="ListenOptions"/>.</returns>
        public static ListenOptions UseHttps(this ListenOptions listenOptions, HttpsConnectionAdapterOptions httpsOptions)
        {
            var loggerFactory = listenOptions.KestrelServerOptions?.ApplicationServices.GetRequiredService <ILoggerFactory>() ?? NullLoggerFactory.Instance;

            listenOptions.IsTls = true;
            listenOptions.Use(next =>
            {
                // Set the list of protocols from listen options
                httpsOptions.HttpProtocols = listenOptions.Protocols;
                var middleware             = new HttpsConnectionMiddleware(next, httpsOptions, loggerFactory);
                return(middleware.OnConnectionAsync);
            });

            return(listenOptions);
        }
Esempio n. 14
0
        public async Task ImmediateFinAfterOnConnectionAsyncClosesGracefully(RequestDelegate requestDelegate)
        {
            var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));

            listenOptions.Use(next => new AsyncConnectionMiddleware(next).OnConnectionAsync);

            var serviceContext = new TestServiceContext(LoggerFactory);

            await using (var server = new TestServer(requestDelegate, serviceContext, listenOptions))
            {
                using (var connection = server.CreateConnection())
                {
                    // FIN
                    connection.ShutdownSend();
                    await connection.WaitForConnectionClose();
                }
            }
        }
Esempio n. 15
0
 internal static ListenOptions UseConnectionTracing(this ListenOptions listenOptions, IConnectionTracingEventSource eventSource)
 {
     listenOptions.Use(next => new ConnectionTracingMiddleware(next, eventSource).OnConnectionAsync);
     return(listenOptions);
 }
Esempio n. 16
0
 public static IConnectionBuilder UseProtocolMultiplexing(this ListenOptions options) =>
 options.Use(next => new ProtocolMultiplexingMiddleware(next).OnConnectionAsync);