From 9969e99ef4170085dae20aab3785d8d15e510dfd Mon Sep 17 00:00:00 2001 From: Dylan Dmitri Gray Date: Mon, 27 May 2019 14:46:14 -0700 Subject: [PATCH] Dylan/request throttle (#10413) * request throttling -- initial implementation * prevented semaphore leak; added xml docs * small doc fixes * reference document * Added internals folder, added structured logging, * removed typo'd dependency * no default MaxConcurrentRequests; other polishing * renamed SemaphoreWrapper->RequestQueue; cleanup * moved SyncPoint; prevented possible semaphore leak * adjusting feedback * regen refs * Final changes! --- ...rosoft.AspNetCore.RequestThrottling.csproj | 4 +- ...NetCore.RequestThrottling.netcoreapp3.0.cs | 21 ++++ .../sample/RequestThrottlingSample.csproj | 4 +- .../RequestThrottling/sample/Startup.cs | 19 ++- .../src/Internal/RequestQueue.cs | 64 ++++++++++ ...rosoft.AspNetCore.RequestThrottling.csproj | 8 +- .../src/RequestThrottlingExtensions.cs | 29 +++++ .../src/RequestThrottlingMiddleware.cs | 116 ++++++++++++++++++ .../src/RequestThrottlingOptions.cs | 19 +++ .../RequestThrottling/src/SemaphoreWrapper.cs | 38 ------ ....AspNetCore.RequestThrottling.Tests.csproj | 8 +- .../RequestThrottling/test/MiddlewareTests.cs | 86 +++++++++++++ ...reWrapperTests.cs => RequestQueueTests.cs} | 42 ++++--- .../RequestThrottling/test/TestUtils.cs | 28 +++++ .../samples/ResponseCachingSample/Startup.cs | 2 +- ...icrosoft.AspNetCore.ResponseCaching.csproj | 2 +- .../Microsoft.AspNetCore.ANCMSymbols.csproj | 10 ++ ...ft.AspNetCore.ANCMSymbols.netcoreapp3.0.cs | 3 + .../SyncPoint}/SyncPoint.cs | 2 +- ...HttpConnectionTests.ConnectionLifecycle.cs | 5 +- .../HubConnectionTests.ConnectionLifecycle.cs | 1 + ...oft.AspNetCore.SignalR.Client.Tests.csproj | 3 +- .../ServerSentEventsTransportTests.cs | 1 + .../test/HttpConnectionDispatcherTests.cs | 1 + ...t.AspNetCore.Http.Connections.Tests.csproj | 3 +- .../Microsoft.AspNetCore.SignalR.Tests.csproj | 7 +- .../SignalR/test/SerializedHubMessageTests.cs | 1 + 27 files changed, 455 insertions(+), 72 deletions(-) create mode 100644 src/Middleware/RequestThrottling/src/Internal/RequestQueue.cs create mode 100644 src/Middleware/RequestThrottling/src/RequestThrottlingExtensions.cs create mode 100644 src/Middleware/RequestThrottling/src/RequestThrottlingMiddleware.cs create mode 100644 src/Middleware/RequestThrottling/src/RequestThrottlingOptions.cs delete mode 100644 src/Middleware/RequestThrottling/src/SemaphoreWrapper.cs create mode 100644 src/Middleware/RequestThrottling/test/MiddlewareTests.cs rename src/Middleware/RequestThrottling/test/{SemaphoreWrapperTests.cs => RequestQueueTests.cs} (60%) create mode 100644 src/Middleware/RequestThrottling/test/TestUtils.cs create mode 100644 src/Servers/IIS/AspNetCoreModuleV2/ref/Microsoft.AspNetCore.ANCMSymbols.csproj create mode 100644 src/Servers/IIS/AspNetCoreModuleV2/ref/Microsoft.AspNetCore.ANCMSymbols.netcoreapp3.0.cs rename src/{SignalR/common/testassets/Tests.Utils => Shared/SyncPoint}/SyncPoint.cs (98%) diff --git a/src/Middleware/RequestThrottling/ref/Microsoft.AspNetCore.RequestThrottling.csproj b/src/Middleware/RequestThrottling/ref/Microsoft.AspNetCore.RequestThrottling.csproj index 0a1bcdd0b9..8e8c1dfce6 100644 --- a/src/Middleware/RequestThrottling/ref/Microsoft.AspNetCore.RequestThrottling.csproj +++ b/src/Middleware/RequestThrottling/ref/Microsoft.AspNetCore.RequestThrottling.csproj @@ -5,6 +5,8 @@ - + + + diff --git a/src/Middleware/RequestThrottling/ref/Microsoft.AspNetCore.RequestThrottling.netcoreapp3.0.cs b/src/Middleware/RequestThrottling/ref/Microsoft.AspNetCore.RequestThrottling.netcoreapp3.0.cs index 618082bc4a..b5a3acf406 100644 --- a/src/Middleware/RequestThrottling/ref/Microsoft.AspNetCore.RequestThrottling.netcoreapp3.0.cs +++ b/src/Middleware/RequestThrottling/ref/Microsoft.AspNetCore.RequestThrottling.netcoreapp3.0.cs @@ -1,3 +1,24 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +namespace Microsoft.AspNetCore.Builder +{ + public static partial class RequestThrottlingExtensions + { + public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRequestThrottling(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { throw null; } + } +} +namespace Microsoft.AspNetCore.RequestThrottling +{ + public partial class RequestThrottlingMiddleware + { + public RequestThrottlingMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Options.IOptions options) { } + [System.Diagnostics.DebuggerStepThroughAttribute] + public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) { throw null; } + } + public partial class RequestThrottlingOptions + { + public RequestThrottlingOptions() { } + public int? MaxConcurrentRequests { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } +} diff --git a/src/Middleware/RequestThrottling/sample/RequestThrottlingSample.csproj b/src/Middleware/RequestThrottling/sample/RequestThrottlingSample.csproj index 0f80e6516a..9f49f115c0 100644 --- a/src/Middleware/RequestThrottling/sample/RequestThrottlingSample.csproj +++ b/src/Middleware/RequestThrottling/sample/RequestThrottlingSample.csproj @@ -1,13 +1,13 @@ - + netcoreapp3.0 - + diff --git a/src/Middleware/RequestThrottling/sample/Startup.cs b/src/Middleware/RequestThrottling/sample/Startup.cs index 95a94be56d..113f48d860 100644 --- a/src/Middleware/RequestThrottling/sample/Startup.cs +++ b/src/Middleware/RequestThrottling/sample/Startup.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System.IO; -using System.Linq; -using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.RequestThrottling; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -19,13 +19,20 @@ namespace RequestThrottlingSample // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + services.Configure(options => + { + options.MaxConcurrentRequests = 2; + }); } - public void Configure(IApplicationBuilder app, IWebHostEnvironment environment) + public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { + app.UseRequestThrottling(); + app.Run(async context => { - await context.Response.WriteAsync("Hello world!"); + await context.Response.WriteAsync("Hello Request Throttling!

"); + await Task.Delay(1000); }); } diff --git a/src/Middleware/RequestThrottling/src/Internal/RequestQueue.cs b/src/Middleware/RequestThrottling/src/Internal/RequestQueue.cs new file mode 100644 index 0000000000..a09ddeb79d --- /dev/null +++ b/src/Middleware/RequestThrottling/src/Internal/RequestQueue.cs @@ -0,0 +1,64 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.RequestThrottling.Internal +{ + internal class RequestQueue : IDisposable + { + private SemaphoreSlim _semaphore; + private object _waitingRequestsLock = new object(); + public readonly int MaxConcurrentRequests; + public int WaitingRequests { get; private set; } + + public RequestQueue(int maxConcurrentRequests) + { + MaxConcurrentRequests = maxConcurrentRequests; + _semaphore = new SemaphoreSlim(maxConcurrentRequests); + } + + public async Task EnterQueue() + { + var waitInQueueTask = _semaphore.WaitAsync(); + + var needsToWaitOnQueue = !waitInQueueTask.IsCompletedSuccessfully; + if (needsToWaitOnQueue) + { + lock (_waitingRequestsLock) + { + WaitingRequests++; + } + + await waitInQueueTask; + + lock (_waitingRequestsLock) + { + WaitingRequests--; + } + } + } + + public void Release() + { + _semaphore.Release(); + } + + public int Count + { + get => _semaphore.CurrentCount; + } + + public int ConcurrentRequests + { + get => MaxConcurrentRequests - _semaphore.CurrentCount; + } + + public void Dispose() + { + _semaphore.Dispose(); + } + } +} diff --git a/src/Middleware/RequestThrottling/src/Microsoft.AspNetCore.RequestThrottling.csproj b/src/Middleware/RequestThrottling/src/Microsoft.AspNetCore.RequestThrottling.csproj index 5014e9cec5..0090f373c0 100644 --- a/src/Middleware/RequestThrottling/src/Microsoft.AspNetCore.RequestThrottling.csproj +++ b/src/Middleware/RequestThrottling/src/Microsoft.AspNetCore.RequestThrottling.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core middleware for queuing incoming HTTP requests, to avoid threadpool starvation. @@ -7,4 +7,10 @@ aspnetcore;queue;queuing + + + + + + diff --git a/src/Middleware/RequestThrottling/src/RequestThrottlingExtensions.cs b/src/Middleware/RequestThrottling/src/RequestThrottlingExtensions.cs new file mode 100644 index 0000000000..17968b44d5 --- /dev/null +++ b/src/Middleware/RequestThrottling/src/RequestThrottlingExtensions.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.RequestThrottling; + +namespace Microsoft.AspNetCore.Builder +{ + /// + /// Extension methods for adding the to an application. + /// + public static class RequestThrottlingExtensions + { + /// + /// Adds the to limit the number of concurrently-executing requests. + /// + /// The . + /// The . + public static IApplicationBuilder UseRequestThrottling(this IApplicationBuilder app) + { + if (app == null) + { + throw new ArgumentNullException(nameof(app)); + } + + return app.UseMiddleware(); + } + } +} diff --git a/src/Middleware/RequestThrottling/src/RequestThrottlingMiddleware.cs b/src/Middleware/RequestThrottling/src/RequestThrottlingMiddleware.cs new file mode 100644 index 0000000000..9eaec8cfbc --- /dev/null +++ b/src/Middleware/RequestThrottling/src/RequestThrottlingMiddleware.cs @@ -0,0 +1,116 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.RequestThrottling.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.RequestThrottling +{ + /// + /// Limits the number of concurrent requests allowed in the application. + /// + public class RequestThrottlingMiddleware + { + private readonly RequestQueue _requestQueue; + private readonly RequestThrottlingOptions _options; + private readonly RequestDelegate _next; + private readonly ILogger _logger; + + /// + /// Creates a new . + /// + /// The representing the next middleware in the pipeline. + /// The used for logging. + /// The containing the initialization parameters. + public RequestThrottlingMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IOptions options) + { + if (options.Value.MaxConcurrentRequests == null) + { + throw new ArgumentException("The value of 'options.MaxConcurrentRequests' must be specified.", nameof(options)); + } + + _next = next; + _logger = loggerFactory.CreateLogger(); + _options = options.Value; + _requestQueue = new RequestQueue(_options.MaxConcurrentRequests.Value); + } + + /// + /// Invokes the logic of the middleware. + /// + /// The . + /// A that completes when the request leaves. + public async Task Invoke(HttpContext context) + { + var waitInQueueTask = _requestQueue.EnterQueue(); + + if (waitInQueueTask.IsCompletedSuccessfully) + { + RequestThrottlingLog.RequestRunImmediately(_logger); + } + else + { + RequestThrottlingLog.RequestEnqueued(_logger, WaitingRequests); + await waitInQueueTask; + RequestThrottlingLog.RequestDequeued(_logger, WaitingRequests); + } + + try + { + await _next(context); + } + finally + { + _requestQueue.Release(); + } + } + + /// + /// The number of live requests that are downstream from this middleware. + /// Cannot exceeed . + /// + internal int ConcurrentRequests + { + get => _requestQueue.ConcurrentRequests; + } + + /// + /// Number of requests currently enqueued and waiting to be processed. + /// + internal int WaitingRequests + { + get => _requestQueue.WaitingRequests; + } + + private static class RequestThrottlingLog + { + private static readonly Action _requestEnqueued = + LoggerMessage.Define(LogLevel.Debug, new EventId(1, "RequestEnqueued"), "Concurrent request limit reached, queuing request. Current queue length: {QueuedRequests}."); + + private static readonly Action _requestDequeued = + LoggerMessage.Define(LogLevel.Debug, new EventId(2, "RequestDequeued"), "Request dequeued. Current queue length: {QueuedRequests}."); + + private static readonly Action _requestRunImmediately = + LoggerMessage.Define(LogLevel.Debug, new EventId(3, "RequestRunImmediately"), "Concurrent request limit has not been reached, running request immediately."); + + internal static void RequestEnqueued(ILogger logger, int queuedRequests) + { + _requestEnqueued(logger, queuedRequests, null); + } + + internal static void RequestDequeued(ILogger logger, int queuedRequests) + { + _requestDequeued(logger, queuedRequests, null); + } + + internal static void RequestRunImmediately(ILogger logger) + { + _requestRunImmediately(logger, null); + } + } + } +} diff --git a/src/Middleware/RequestThrottling/src/RequestThrottlingOptions.cs b/src/Middleware/RequestThrottling/src/RequestThrottlingOptions.cs new file mode 100644 index 0000000000..64a832640f --- /dev/null +++ b/src/Middleware/RequestThrottling/src/RequestThrottlingOptions.cs @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.RequestThrottling; + +namespace Microsoft.AspNetCore.RequestThrottling +{ + /// + /// Specifies options for the . + /// + public class RequestThrottlingOptions + { + /// + /// Maximum number of concurrent requests. Any extras will be queued on the server. + /// This is null by default because the correct value is application specific. This option must be configured by the application. + /// + public int? MaxConcurrentRequests { get; set; } + } +} diff --git a/src/Middleware/RequestThrottling/src/SemaphoreWrapper.cs b/src/Middleware/RequestThrottling/src/SemaphoreWrapper.cs deleted file mode 100644 index 4c79b94777..0000000000 --- a/src/Middleware/RequestThrottling/src/SemaphoreWrapper.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.RequestThrottling -{ - internal class SemaphoreWrapper : IDisposable - { - private SemaphoreSlim _semaphore; - - public SemaphoreWrapper(int queueLength) - { - _semaphore = new SemaphoreSlim(queueLength); - } - - public Task EnterQueue() - { - return _semaphore.WaitAsync(); - } - - public void LeaveQueue() - { - _semaphore.Release(); - } - - public int Count - { - get => _semaphore.CurrentCount; - } - - public void Dispose() - { - _semaphore.Dispose(); - } - } -} diff --git a/src/Middleware/RequestThrottling/test/Microsoft.AspNetCore.RequestThrottling.Tests.csproj b/src/Middleware/RequestThrottling/test/Microsoft.AspNetCore.RequestThrottling.Tests.csproj index 8c0dd8e989..78b1c88692 100644 --- a/src/Middleware/RequestThrottling/test/Microsoft.AspNetCore.RequestThrottling.Tests.csproj +++ b/src/Middleware/RequestThrottling/test/Microsoft.AspNetCore.RequestThrottling.Tests.csproj @@ -1,10 +1,16 @@ - + netcoreapp3.0 + + + + + + diff --git a/src/Middleware/RequestThrottling/test/MiddlewareTests.cs b/src/Middleware/RequestThrottling/test/MiddlewareTests.cs new file mode 100644 index 0000000000..8124cddb49 --- /dev/null +++ b/src/Middleware/RequestThrottling/test/MiddlewareTests.cs @@ -0,0 +1,86 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information + +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Internal; +using Xunit; + +namespace Microsoft.AspNetCore.RequestThrottling.Tests +{ + public class MiddlewareTests + { + [Fact] + public async Task RequestsCanEnterIfSpaceAvailible() + { + var middleware = TestUtils.CreateTestMiddleWare(maxConcurrentRequests: 1); + var context = new DefaultHttpContext(); + + // a request should go through with no problems + await middleware.Invoke(context).OrTimeout(); + } + + [Fact] + public async Task SemaphoreStatePreservedIfRequestsError() + { + var middleware = TestUtils.CreateTestMiddleWare( + maxConcurrentRequests: 1, + next: httpContext => + { + throw new DivideByZeroException(); + }); + + Assert.Equal(0, middleware.ConcurrentRequests); + + await Assert.ThrowsAsync(() => middleware.Invoke(new DefaultHttpContext())); + + Assert.Equal(0, middleware.ConcurrentRequests); + } + + [Fact] + public async Task QueuedRequestsContinueWhenSpaceBecomesAvailible() + { + var blocker = new SyncPoint(); + var firstRequest = true; + + var middleware = TestUtils.CreateTestMiddleWare( + maxConcurrentRequests: 1, + next: httpContext => + { + if (firstRequest) + { + firstRequest = false; + return blocker.WaitToContinue(); + } + return Task.CompletedTask; + }); + + // t1 (as the first request) is blocked by the tcs blocker + var t1 = middleware.Invoke(new DefaultHttpContext()); + Assert.Equal(1, middleware.ConcurrentRequests); + Assert.Equal(0, middleware.WaitingRequests); + + // t2 is blocked from entering the server since t1 already exists there + // note: increasing MaxConcurrentRequests would allow t2 through while t1 is blocked + var t2 = middleware.Invoke(new DefaultHttpContext()); + Assert.Equal(1, middleware.ConcurrentRequests); + Assert.Equal(1, middleware.WaitingRequests); + + // unblock the first task, and the second should follow + blocker.Continue(); + await t1.OrTimeout(); + await t2.OrTimeout(); + } + + [Fact] + public void InvalidArgumentIfMaxConcurrentRequestsIsNull() + { + var ex = Assert.Throws(() => + { + TestUtils.CreateTestMiddleWare(maxConcurrentRequests: null); + }); + Assert.Equal("options", ex.ParamName); + } + } +} diff --git a/src/Middleware/RequestThrottling/test/SemaphoreWrapperTests.cs b/src/Middleware/RequestThrottling/test/RequestQueueTests.cs similarity index 60% rename from src/Middleware/RequestThrottling/test/SemaphoreWrapperTests.cs rename to src/Middleware/RequestThrottling/test/RequestQueueTests.cs index b5cdfce18f..67eeda5d67 100644 --- a/src/Middleware/RequestThrottling/test/SemaphoreWrapperTests.cs +++ b/src/Middleware/RequestThrottling/test/RequestQueueTests.cs @@ -1,34 +1,48 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Xunit; -using System.Threading; using System.Threading.Tasks; -using System; -using System.Runtime.CompilerServices; -using Microsoft.AspNetCore.Testing; +using Microsoft.AspNetCore.RequestThrottling.Internal; +using Xunit; namespace Microsoft.AspNetCore.RequestThrottling.Tests { - public class SemaphoreWrapperTests + public class RequestQueueTests { [Fact] - public async Task TracksQueueLength() + public async Task LimitsIncomingRequests() { - using var s = new SemaphoreWrapper(1); + using var s = new RequestQueue(1); Assert.Equal(1, s.Count); await s.EnterQueue().OrTimeout(); Assert.Equal(0, s.Count); - s.LeaveQueue(); + s.Release(); Assert.Equal(1, s.Count); } + [Fact] + public async Task TracksQueueLength() + { + using var s = new RequestQueue(1); + Assert.Equal(0, s.WaitingRequests); + + await s.EnterQueue(); + Assert.Equal(0, s.WaitingRequests); + + var enterQueueTask = s.EnterQueue(); + Assert.Equal(1, s.WaitingRequests); + + s.Release(); + await enterQueueTask; + Assert.Equal(0, s.WaitingRequests); + } + [Fact] public void DoesNotWaitIfSpaceAvailible() { - using var s = new SemaphoreWrapper(2); + using var s = new RequestQueue(2); var t1 = s.EnterQueue(); Assert.True(t1.IsCompleted); @@ -43,21 +57,21 @@ namespace Microsoft.AspNetCore.RequestThrottling.Tests [Fact] public async Task WaitsIfNoSpaceAvailible() { - using var s = new SemaphoreWrapper(1); + using var s = new RequestQueue(1); await s.EnterQueue().OrTimeout(); var waitingTask = s.EnterQueue(); Assert.False(waitingTask.IsCompleted); - s.LeaveQueue(); + s.Release(); await waitingTask.OrTimeout(); } [Fact] public async Task IsEncapsulated() { - using var s1 = new SemaphoreWrapper(1); - using var s2 = new SemaphoreWrapper(1); + using var s1 = new RequestQueue(1); + using var s2 = new RequestQueue(1); await s1.EnterQueue().OrTimeout(); await s2.EnterQueue().OrTimeout(); diff --git a/src/Middleware/RequestThrottling/test/TestUtils.cs b/src/Middleware/RequestThrottling/test/TestUtils.cs new file mode 100644 index 0000000000..438d08ab8d --- /dev/null +++ b/src/Middleware/RequestThrottling/test/TestUtils.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.RequestThrottling; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.RequestThrottling.Tests +{ + public static class TestUtils + { + public static RequestThrottlingMiddleware CreateTestMiddleWare(int? maxConcurrentRequests, RequestDelegate next = null) + { + var options = new RequestThrottlingOptions + { + MaxConcurrentRequests = maxConcurrentRequests + }; + + return new RequestThrottlingMiddleware( + next: next ?? (context => Task.CompletedTask), + loggerFactory: NullLoggerFactory.Instance, + options: Options.Create(options) + ); + } + } +} diff --git a/src/Middleware/ResponseCaching/samples/ResponseCachingSample/Startup.cs b/src/Middleware/ResponseCaching/samples/ResponseCachingSample/Startup.cs index ca2e7fbcf3..6184a36946 100644 --- a/src/Middleware/ResponseCaching/samples/ResponseCachingSample/Startup.cs +++ b/src/Middleware/ResponseCaching/samples/ResponseCachingSample/Startup.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; diff --git a/src/Middleware/ResponseCaching/src/Microsoft.AspNetCore.ResponseCaching.csproj b/src/Middleware/ResponseCaching/src/Microsoft.AspNetCore.ResponseCaching.csproj index 9611dfbdaf..ef8199808c 100644 --- a/src/Middleware/ResponseCaching/src/Microsoft.AspNetCore.ResponseCaching.csproj +++ b/src/Middleware/ResponseCaching/src/Microsoft.AspNetCore.ResponseCaching.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core middleware for caching HTTP responses on the server. diff --git a/src/Servers/IIS/AspNetCoreModuleV2/ref/Microsoft.AspNetCore.ANCMSymbols.csproj b/src/Servers/IIS/AspNetCoreModuleV2/ref/Microsoft.AspNetCore.ANCMSymbols.csproj new file mode 100644 index 0000000000..36c3a47a9a --- /dev/null +++ b/src/Servers/IIS/AspNetCoreModuleV2/ref/Microsoft.AspNetCore.ANCMSymbols.csproj @@ -0,0 +1,10 @@ + + + + netcoreapp3.0 + + + + + + diff --git a/src/Servers/IIS/AspNetCoreModuleV2/ref/Microsoft.AspNetCore.ANCMSymbols.netcoreapp3.0.cs b/src/Servers/IIS/AspNetCoreModuleV2/ref/Microsoft.AspNetCore.ANCMSymbols.netcoreapp3.0.cs new file mode 100644 index 0000000000..618082bc4a --- /dev/null +++ b/src/Servers/IIS/AspNetCoreModuleV2/ref/Microsoft.AspNetCore.ANCMSymbols.netcoreapp3.0.cs @@ -0,0 +1,3 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + diff --git a/src/SignalR/common/testassets/Tests.Utils/SyncPoint.cs b/src/Shared/SyncPoint/SyncPoint.cs similarity index 98% rename from src/SignalR/common/testassets/Tests.Utils/SyncPoint.cs rename to src/Shared/SyncPoint/SyncPoint.cs index 55f4a034d5..ccf36d59df 100644 --- a/src/SignalR/common/testassets/Tests.Utils/SyncPoint.cs +++ b/src/Shared/SyncPoint/SyncPoint.cs @@ -4,7 +4,7 @@ using System; using System.Threading.Tasks; -namespace Microsoft.AspNetCore.SignalR.Tests +namespace Microsoft.AspNetCore.Internal { public class SyncPoint { diff --git a/src/SignalR/clients/csharp/Client/test/UnitTests/HttpConnectionTests.ConnectionLifecycle.cs b/src/SignalR/clients/csharp/Client/test/UnitTests/HttpConnectionTests.ConnectionLifecycle.cs index 2088ef3927..61821226b2 100644 --- a/src/SignalR/clients/csharp/Client/test/UnitTests/HttpConnectionTests.ConnectionLifecycle.cs +++ b/src/SignalR/clients/csharp/Client/test/UnitTests/HttpConnectionTests.ConnectionLifecycle.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Http.Connections.Client; using Microsoft.AspNetCore.Http.Connections.Client.Internal; +using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; @@ -90,8 +91,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests var startCounter = 0; var expected = new Exception("Transport failed to start"); - // We have 4 cases here. Falling back once, falling back twice and each of these - // with WebSockets available and not. If Websockets aren't available and + // We have 4 cases here. Falling back once, falling back twice and each of these + // with WebSockets available and not. If Websockets aren't available and // we can't to test the fallback once scenario we don't decrement the passthreshold // because we still try to start twice (SSE and LP). if (!TestHelpers.IsWebSocketsSupported() && passThreshold > 2) diff --git a/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionTests.ConnectionLifecycle.cs b/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionTests.ConnectionLifecycle.cs index f48742474b..647aa433ca 100644 --- a/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionTests.ConnectionLifecycle.cs +++ b/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionTests.ConnectionLifecycle.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; +using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.SignalR.Protocol; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.Extensions.DependencyInjection; diff --git a/src/SignalR/clients/csharp/Client/test/UnitTests/Microsoft.AspNetCore.SignalR.Client.Tests.csproj b/src/SignalR/clients/csharp/Client/test/UnitTests/Microsoft.AspNetCore.SignalR.Client.Tests.csproj index a2b40fbe25..cc45556edd 100644 --- a/src/SignalR/clients/csharp/Client/test/UnitTests/Microsoft.AspNetCore.SignalR.Client.Tests.csproj +++ b/src/SignalR/clients/csharp/Client/test/UnitTests/Microsoft.AspNetCore.SignalR.Client.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.0 @@ -8,6 +8,7 @@ + diff --git a/src/SignalR/clients/csharp/Client/test/UnitTests/ServerSentEventsTransportTests.cs b/src/SignalR/clients/csharp/Client/test/UnitTests/ServerSentEventsTransportTests.cs index 421e1cef61..aa3c41bbed 100644 --- a/src/SignalR/clients/csharp/Client/test/UnitTests/ServerSentEventsTransportTests.cs +++ b/src/SignalR/clients/csharp/Client/test/UnitTests/ServerSentEventsTransportTests.cs @@ -11,6 +11,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections.Client.Internal; +using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.Extensions.Logging.Testing; using Moq; diff --git a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs index 5b4c164ce3..2fcf129790 100644 --- a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs +++ b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs @@ -21,6 +21,7 @@ using Microsoft.AspNetCore.Http.Connections.Internal; using Microsoft.AspNetCore.Http.Connections.Internal.Transports; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Internal; +using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing.xunit; diff --git a/src/SignalR/common/Http.Connections/test/Microsoft.AspNetCore.Http.Connections.Tests.csproj b/src/SignalR/common/Http.Connections/test/Microsoft.AspNetCore.Http.Connections.Tests.csproj index 6c03dfe4eb..1f6b36a8ba 100644 --- a/src/SignalR/common/Http.Connections/test/Microsoft.AspNetCore.Http.Connections.Tests.csproj +++ b/src/SignalR/common/Http.Connections/test/Microsoft.AspNetCore.Http.Connections.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.0 @@ -6,6 +6,7 @@ + diff --git a/src/SignalR/server/SignalR/test/Microsoft.AspNetCore.SignalR.Tests.csproj b/src/SignalR/server/SignalR/test/Microsoft.AspNetCore.SignalR.Tests.csproj index c4fd5fd37b..24958a00b6 100644 --- a/src/SignalR/server/SignalR/test/Microsoft.AspNetCore.SignalR.Tests.csproj +++ b/src/SignalR/server/SignalR/test/Microsoft.AspNetCore.SignalR.Tests.csproj @@ -1,9 +1,12 @@ - + netcoreapp3.0 + + + @@ -23,4 +26,4 @@ - + \ No newline at end of file diff --git a/src/SignalR/server/SignalR/test/SerializedHubMessageTests.cs b/src/SignalR/server/SignalR/test/SerializedHubMessageTests.cs index b69952b523..da55a5e675 100644 --- a/src/SignalR/server/SignalR/test/SerializedHubMessageTests.cs +++ b/src/SignalR/server/SignalR/test/SerializedHubMessageTests.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.SignalR.Protocol; using Xunit;