diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs index 2fafdb58a57b..6bc2b7c168b2 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs @@ -139,6 +139,14 @@ private void ParseRequestLine(TRequestHandler handler, ReadOnlySpan reques // Consume space offset++; + while ((uint)offset < (uint)requestLine.Length + && requestLine[offset] == ByteSpace) + { + // It's invalid to have multiple spaces between the url resource and version + // but some clients do it. Skip them. + offset++; + } + // Version + CR is 9 bytes which should take us to .Length // LF should have been dropped prior to method call if ((uint)offset + 9 != (uint)requestLine.Length || requestLine[offset + 8] != ByteCR) diff --git a/src/Servers/Kestrel/shared/test/HttpParsingData.cs b/src/Servers/Kestrel/shared/test/HttpParsingData.cs index f259dd9232ee..cc3451baef66 100644 --- a/src/Servers/Kestrel/shared/test/HttpParsingData.cs +++ b/src/Servers/Kestrel/shared/test/HttpParsingData.cs @@ -76,7 +76,9 @@ public static IEnumerable RequestLineValidData var httpVersions = new[] { "HTTP/1.0", - "HTTP/1.1" + "HTTP/1.1", + " HTTP/1.1", + " HTTP/1.1" }; return from method in methods @@ -91,7 +93,7 @@ select new[] $"{path.Item1}", $"{path.Item2}", queryString, - httpVersion + httpVersion.Trim() }; } } @@ -164,6 +166,12 @@ public static IEnumerable RequestLineInvalidData "GET / HTTP/1.1\n", "GET / HTTP/1.0\rA\n", "GET / HTTP/1.1\ra\n", + "GET / HTTP/1.1\r\n", + "GET / HTTP/1.1\r\n", + "GET / HTTP/1.1\r\n", + "GET / HTTP/1.1\r\n", + "GET / HTTP/1.1 \r\n", + "GET / HTTP/1.1 \r\n", "GET / H\r\n", "GET / HT\r\n", "GET / HTT\r\n", @@ -195,6 +203,12 @@ public static IEnumerable RequestLineInvalidData "CUSTOM / HTTP/1.1\n", "CUSTOM / HTTP/1.0\rA\n", "CUSTOM / HTTP/1.1\ra\n", + "CUSTOM / HTTP/1.1\r\n", + "CUSTOM / HTTP/1.1\r\n", + "CUSTOM / HTTP/1.1\r\n", + "CUSTOM / HTTP/1.1\r\n", + "CUSTOM / HTTP/1.1 \r\n", + "CUSTOM / HTTP/1.1 \r\n", "CUSTOM / H\r\n", "CUSTOM / HT\r\n", "CUSTOM / HTT\r\n",