Răsfoiți Sursa

Dispose rejected requests (#28579)

* Dispose rejected requests
- Rejected requests never get scheduled, so make sure they get disposed before getting the new request from the queue

* Handle request validation throwing
- We also want to dispose if request validation fails
- Log an error if it throws
David Fowler 5 ani în urmă
părinte
comite
b716f7abec

+ 17 - 9
src/Servers/HttpSys/src/HttpSysListener.cs

@@ -285,19 +285,27 @@ namespace Microsoft.AspNetCore.Server.HttpSys
             return acceptContext.AcceptAsync();
         }
 
-        internal unsafe bool ValidateRequest(NativeRequestContext requestMemory)
+        internal bool ValidateRequest(NativeRequestContext requestMemory)
         {
-            // Block potential DOS attacks
-            if (requestMemory.UnknownHeaderCount > UnknownHeaderLimit)
+            try
             {
-                SendError(requestMemory.RequestId, StatusCodes.Status400BadRequest, authChallenges: null);
-                return false;
-            }
+                // Block potential DOS attacks
+                if (requestMemory.UnknownHeaderCount > UnknownHeaderLimit)
+                {
+                    SendError(requestMemory.RequestId, StatusCodes.Status400BadRequest, authChallenges: null);
+                    return false;
+                }
 
-            if (!Options.Authentication.AllowAnonymous && !requestMemory.CheckAuthenticated())
+                if (!Options.Authentication.AllowAnonymous && !requestMemory.CheckAuthenticated())
+                {
+                    SendError(requestMemory.RequestId, StatusCodes.Status401Unauthorized,
+                        AuthenticationManager.GenerateChallenges(Options.Authentication.Schemes));
+                    return false;
+                }
+            }
+            catch (Exception ex)
             {
-                SendError(requestMemory.RequestId, StatusCodes.Status401Unauthorized,
-                    AuthenticationManager.GenerateChallenges(Options.Authentication.Schemes));
+                Logger.LogError(LoggerEventIds.RequestValidationFailed, ex, "Error validating request {RequestId}", requestMemory.RequestId);
                 return false;
             }
 

+ 1 - 0
src/Servers/HttpSys/src/LoggerEventIds.cs

@@ -50,5 +50,6 @@ namespace Microsoft.AspNetCore.Server.HttpSys
         public static EventId DisconnectTriggered = new EventId(44, "DisconnectTriggered");
         public static EventId ListenerStopError = new EventId(45, "ListenerStopError");
         public static EventId ListenerDisposing = new EventId(46, "ListenerDisposing");
+        public static EventId RequestValidationFailed = new EventId(47, "RequestValidationFailed");
     }
 }

+ 3 - 0
src/Servers/HttpSys/src/MessagePump.cs

@@ -192,6 +192,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
 
                     if (!Listener.ValidateRequest(requestContext))
                     {
+                        // Dispose the request
+                        requestContext.Dispose();
+
                         // If either of these is false then a response has already been sent to the client, so we can accept the next request
                         continue;
                     }

+ 2 - 0
src/Servers/HttpSys/test/FunctionalTests/Listener/Utilities.cs

@@ -127,6 +127,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
                         requestContext.InitializeFeatures();
                         return requestContext;
                     }
+
+                    requestContext.Dispose();
                 }
             }