Verify all request rejections are logged (#1295).
This commit is contained in:
parent
7d94abd606
commit
11c7eb5665
|
|
@ -1,11 +1,15 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
|
|
@ -14,106 +18,102 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
{
|
{
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(InvalidRequestLineData))]
|
[MemberData(nameof(InvalidRequestLineData))]
|
||||||
public async Task TestInvalidRequestLines(string request)
|
public Task TestInvalidRequestLines(string request, string expectedExceptionMessage)
|
||||||
{
|
{
|
||||||
using (var server = new TestServer(context => TaskCache.CompletedTask))
|
return TestBadRequest(
|
||||||
{
|
request,
|
||||||
using (var connection = server.CreateConnection())
|
"400 Bad Request",
|
||||||
{
|
expectedExceptionMessage);
|
||||||
await connection.SendAll(request);
|
|
||||||
await ReceiveBadRequestResponse(connection, "400 Bad Request", server.Context.DateHeaderValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(UnrecognizedHttpVersionData))]
|
[MemberData(nameof(UnrecognizedHttpVersionData))]
|
||||||
public async Task TestInvalidRequestLinesWithUnrecognizedVersion(string httpVersion)
|
public Task TestInvalidRequestLinesWithUnrecognizedVersion(string httpVersion)
|
||||||
{
|
{
|
||||||
using (var server = new TestServer(context => TaskCache.CompletedTask))
|
return TestBadRequest(
|
||||||
{
|
$"GET / {httpVersion}\r\n",
|
||||||
using (var connection = server.CreateConnection())
|
"505 HTTP Version Not Supported",
|
||||||
{
|
$"Unrecognized HTTP version: {httpVersion}");
|
||||||
await connection.SendAll($"GET / {httpVersion}\r\n");
|
|
||||||
await ReceiveBadRequestResponse(connection, "505 HTTP Version Not Supported", server.Context.DateHeaderValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(InvalidRequestHeaderData))]
|
[MemberData(nameof(InvalidRequestHeaderData))]
|
||||||
public async Task TestInvalidHeaders(string rawHeaders)
|
public Task TestInvalidHeaders(string rawHeaders, string expectedExceptionMessage)
|
||||||
{
|
{
|
||||||
using (var server = new TestServer(context => TaskCache.CompletedTask))
|
return TestBadRequest(
|
||||||
{
|
$"GET / HTTP/1.1\r\n{rawHeaders}",
|
||||||
using (var connection = server.CreateConnection())
|
"400 Bad Request",
|
||||||
{
|
expectedExceptionMessage);
|
||||||
await connection.SendAll($"GET / HTTP/1.1\r\n{rawHeaders}");
|
|
||||||
await ReceiveBadRequestResponse(connection, "400 Bad Request", server.Context.DateHeaderValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Theory]
|
||||||
public async Task BadRequestWhenHeaderNameContainsNonASCIICharacters()
|
[InlineData("Hea\0der: value", "Invalid characters in header name.")]
|
||||||
|
[InlineData("Header: va\0lue", "Malformed request: invalid headers.")]
|
||||||
|
[InlineData("Head\x80r: value", "Invalid characters in header name.")]
|
||||||
|
[InlineData("Header: valu\x80", "Malformed request: invalid headers.")]
|
||||||
|
public Task BadRequestWhenHeaderNameContainsNonASCIIOrNullCharacters(string header, string expectedExceptionMessage)
|
||||||
{
|
{
|
||||||
using (var server = new TestServer(context => { return Task.FromResult(0); }))
|
return TestBadRequest(
|
||||||
{
|
$"GET / HTTP/1.1\r\n{header}\r\n\r\n",
|
||||||
using (var connection = server.CreateConnection())
|
"400 Bad Request",
|
||||||
{
|
expectedExceptionMessage);
|
||||||
await connection.SendAll(
|
|
||||||
"GET / HTTP/1.1",
|
|
||||||
"H\u00eb\u00e4d\u00ebr: value",
|
|
||||||
"",
|
|
||||||
"");
|
|
||||||
await ReceiveBadRequestResponse(connection, "400 Bad Request", server.Context.DateHeaderValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("POST")]
|
[InlineData("POST")]
|
||||||
[InlineData("PUT")]
|
[InlineData("PUT")]
|
||||||
public async Task BadRequestIfMethodRequiresLengthButNoContentLengthOrTransferEncodingInRequest(string method)
|
public Task BadRequestIfMethodRequiresLengthButNoContentLengthOrTransferEncodingInRequest(string method)
|
||||||
{
|
{
|
||||||
using (var server = new TestServer(context => { return Task.FromResult(0); }))
|
return TestBadRequest(
|
||||||
{
|
$"{method} / HTTP/1.1\r\n\r\n",
|
||||||
using (var connection = server.CreateConnection())
|
"411 Length Required",
|
||||||
{
|
$"{method} request contains no Content-Length or Transfer-Encoding header");
|
||||||
await connection.Send($"{method} / HTTP/1.1\r\n\r\n");
|
|
||||||
await ReceiveBadRequestResponse(connection, "411 Length Required", server.Context.DateHeaderValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("POST")]
|
[InlineData("POST")]
|
||||||
[InlineData("PUT")]
|
[InlineData("PUT")]
|
||||||
public async Task BadRequestIfMethodRequiresLengthButNoContentLengthInHttp10Request(string method)
|
public Task BadRequestIfMethodRequiresLengthButNoContentLengthInHttp10Request(string method)
|
||||||
{
|
{
|
||||||
using (var server = new TestServer(context => { return Task.FromResult(0); }))
|
return TestBadRequest(
|
||||||
{
|
$"{method} / HTTP/1.0\r\n\r\n",
|
||||||
using (var connection = server.CreateConnection())
|
"400 Bad Request",
|
||||||
{
|
$"{method} request contains no Content-Length header");
|
||||||
await connection.Send($"{method} / HTTP/1.0\r\n\r\n");
|
|
||||||
await ReceiveBadRequestResponse(connection, "400 Bad Request", server.Context.DateHeaderValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("NaN")]
|
[InlineData("NaN")]
|
||||||
[InlineData("-1")]
|
[InlineData("-1")]
|
||||||
public async Task BadRequestIfContentLengthInvalid(string contentLength)
|
public Task BadRequestIfContentLengthInvalid(string contentLength)
|
||||||
{
|
{
|
||||||
using (var server = new TestServer(context => { return Task.FromResult(0); }))
|
return TestBadRequest(
|
||||||
|
$"POST / HTTP/1.1\r\nContent-Length: {contentLength}\r\n\r\n",
|
||||||
|
"400 Bad Request",
|
||||||
|
$"Invalid content length: {contentLength}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task TestBadRequest(string request, string expectedResponseStatusCode, string expectedExceptionMessage)
|
||||||
|
{
|
||||||
|
BadHttpRequestException loggedException = null;
|
||||||
|
var mockKestrelTrace = new Mock<IKestrelTrace>();
|
||||||
|
mockKestrelTrace
|
||||||
|
.Setup(trace => trace.IsEnabled(LogLevel.Information))
|
||||||
|
.Returns(true);
|
||||||
|
mockKestrelTrace
|
||||||
|
.Setup(trace => trace.ConnectionBadRequest(It.IsAny<string>(), It.IsAny<BadHttpRequestException>()))
|
||||||
|
.Callback<string, BadHttpRequestException>((connectionId, exception) => loggedException = exception);
|
||||||
|
|
||||||
|
using (var server = new TestServer(context => TaskCache.CompletedTask, new TestServiceContext { Log = mockKestrelTrace.Object }))
|
||||||
{
|
{
|
||||||
using (var connection = server.CreateConnection())
|
using (var connection = server.CreateConnection())
|
||||||
{
|
{
|
||||||
await connection.SendAll($"GET / HTTP/1.1\r\nContent-Length: {contentLength}\r\n\r\n");
|
await connection.SendAll(request);
|
||||||
await ReceiveBadRequestResponse(connection, "400 Bad Request", server.Context.DateHeaderValue);
|
await ReceiveBadRequestResponse(connection, expectedResponseStatusCode, server.Context.DateHeaderValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mockKestrelTrace.Verify(trace => trace.ConnectionBadRequest(It.IsAny<string>(), It.IsAny<BadHttpRequestException>()));
|
||||||
|
Assert.Equal(expectedExceptionMessage, loggedException.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ReceiveBadRequestResponse(TestConnection connection, string expectedResponseStatusCode, string expectedDateHeaderValue)
|
private async Task ReceiveBadRequestResponse(TestConnection connection, string expectedResponseStatusCode, string expectedDateHeaderValue)
|
||||||
|
|
@ -127,10 +127,25 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
"");
|
"");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<object> InvalidRequestLineData => HttpParsingData.InvalidRequestLineData.Select(data => new[] { data[0] });
|
public static IEnumerable<object> InvalidRequestLineData => HttpParsingData.InvalidRequestLineData
|
||||||
|
.Select(requestLine => new object[]
|
||||||
|
{
|
||||||
|
requestLine,
|
||||||
|
$"Invalid request line: {requestLine.Replace("\r", "<0x0D>").Replace("\n", "<0x0A>")}",
|
||||||
|
})
|
||||||
|
.Concat(HttpParsingData.EncodedNullCharInTargetRequestLines.Select(requestLine => new object[]
|
||||||
|
{
|
||||||
|
requestLine,
|
||||||
|
"Invalid request line."
|
||||||
|
}))
|
||||||
|
.Concat(HttpParsingData.NullCharInTargetRequestLines.Select(requestLine => new object[]
|
||||||
|
{
|
||||||
|
requestLine,
|
||||||
|
"Invalid request line."
|
||||||
|
}));
|
||||||
|
|
||||||
public static TheoryData<string> UnrecognizedHttpVersionData => HttpParsingData.UnrecognizedHttpVersionData;
|
public static TheoryData<string> UnrecognizedHttpVersionData => HttpParsingData.UnrecognizedHttpVersionData;
|
||||||
|
|
||||||
public static IEnumerable<object[]> InvalidRequestHeaderData => HttpParsingData.InvalidRequestHeaderData.Select(data => new[] { data[0] });
|
public static IEnumerable<object[]> InvalidRequestHeaderData => HttpParsingData.InvalidRequestHeaderData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -304,14 +304,14 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AppendThrowsWhenHeaderValueContainsNonASCIICharacters()
|
public void AppendThrowsWhenHeaderNameContainsNonASCIICharacters()
|
||||||
{
|
{
|
||||||
var headers = new FrameRequestHeaders();
|
var headers = new FrameRequestHeaders();
|
||||||
const string key = "\u00141ód\017c";
|
const string key = "\u00141ód\017c";
|
||||||
|
|
||||||
var encoding = Encoding.GetEncoding("iso-8859-1");
|
var encoding = Encoding.GetEncoding("iso-8859-1");
|
||||||
var exception = Assert.Throws<BadHttpRequestException>(
|
var exception = Assert.Throws<BadHttpRequestException>(
|
||||||
() => headers.Append(encoding.GetBytes(key), key));
|
() => headers.Append(encoding.GetBytes(key), "value"));
|
||||||
Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode);
|
Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
@ -759,7 +760,25 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
|
|
||||||
public static IEnumerable<object> ValidRequestLineData => HttpParsingData.ValidRequestLineData;
|
public static IEnumerable<object> ValidRequestLineData => HttpParsingData.ValidRequestLineData;
|
||||||
|
|
||||||
public static IEnumerable<object> InvalidRequestLineData => HttpParsingData.InvalidRequestLineData;
|
public static IEnumerable<object> InvalidRequestLineData => HttpParsingData.InvalidRequestLineData
|
||||||
|
.Select(requestLine => new object[]
|
||||||
|
{
|
||||||
|
requestLine,
|
||||||
|
typeof(BadHttpRequestException),
|
||||||
|
$"Invalid request line: {requestLine.Replace("\r", "<0x0D>").Replace("\n", "<0x0A>")}",
|
||||||
|
})
|
||||||
|
.Concat(HttpParsingData.EncodedNullCharInTargetRequestLines.Select(requestLine => new object[]
|
||||||
|
{
|
||||||
|
requestLine,
|
||||||
|
typeof(InvalidOperationException),
|
||||||
|
"The path contains null characters."
|
||||||
|
}))
|
||||||
|
.Concat(HttpParsingData.NullCharInTargetRequestLines.Select(requestLine => new object[]
|
||||||
|
{
|
||||||
|
requestLine,
|
||||||
|
typeof(InvalidOperationException),
|
||||||
|
new InvalidOperationException().Message
|
||||||
|
}));
|
||||||
|
|
||||||
public static TheoryData<string> UnrecognizedHttpVersionData => HttpParsingData.UnrecognizedHttpVersionData;
|
public static TheoryData<string> UnrecognizedHttpVersionData => HttpParsingData.UnrecognizedHttpVersionData;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Testing
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
|
@ -71,150 +70,118 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// All these test cases must end in '\n', otherwise the server will spin forever
|
public static IEnumerable<string> InvalidRequestLineData => new[]
|
||||||
public static IEnumerable<object[]> InvalidRequestLineData
|
|
||||||
{
|
{
|
||||||
get
|
"G\r\n",
|
||||||
{
|
"GE\r\n",
|
||||||
var invalidRequestLines = new[]
|
"GET\r\n",
|
||||||
{
|
"GET \r\n",
|
||||||
"G\r\n",
|
"GET /\r\n",
|
||||||
"GE\r\n",
|
"GET / \r\n",
|
||||||
"GET\r\n",
|
"GET/HTTP/1.1\r\n",
|
||||||
"GET \r\n",
|
"GET /HTTP/1.1\r\n",
|
||||||
"GET /\r\n",
|
" \r\n",
|
||||||
"GET / \r\n",
|
" \r\n",
|
||||||
"GET/HTTP/1.1\r\n",
|
"/ HTTP/1.1\r\n",
|
||||||
"GET /HTTP/1.1\r\n",
|
" / HTTP/1.1\r\n",
|
||||||
" \r\n",
|
"/ \r\n",
|
||||||
" \r\n",
|
"GET \r\n",
|
||||||
"/ HTTP/1.1\r\n",
|
"GET HTTP/1.0\r\n",
|
||||||
" / HTTP/1.1\r\n",
|
"GET HTTP/1.1\r\n",
|
||||||
"/ \r\n",
|
"GET / \n",
|
||||||
"GET \r\n",
|
"GET / HTTP/1.0\n",
|
||||||
"GET HTTP/1.0\r\n",
|
"GET / HTTP/1.1\n",
|
||||||
"GET HTTP/1.1\r\n",
|
"GET / HTTP/1.0\rA\n",
|
||||||
"GET / \n",
|
"GET / HTTP/1.1\ra\n",
|
||||||
"GET / HTTP/1.0\n",
|
"GET? / HTTP/1.1\r\n",
|
||||||
"GET / HTTP/1.1\n",
|
"GET ? HTTP/1.1\r\n",
|
||||||
"GET / HTTP/1.0\rA\n",
|
"GET /a?b=cHTTP/1.1\r\n",
|
||||||
"GET / HTTP/1.1\ra\n",
|
"GET /a%20bHTTP/1.1\r\n",
|
||||||
"GET? / HTTP/1.1\r\n",
|
"GET /a%20b?c=dHTTP/1.1\r\n",
|
||||||
"GET ? HTTP/1.1\r\n",
|
"GET %2F HTTP/1.1\r\n",
|
||||||
"GET /a?b=cHTTP/1.1\r\n",
|
"GET %00 HTTP/1.1\r\n",
|
||||||
"GET /a%20bHTTP/1.1\r\n",
|
"CUSTOM \r\n",
|
||||||
"GET /a%20b?c=dHTTP/1.1\r\n",
|
"CUSTOM /\r\n",
|
||||||
"GET %2F HTTP/1.1\r\n",
|
"CUSTOM / \r\n",
|
||||||
"GET %00 HTTP/1.1\r\n",
|
"CUSTOM /HTTP/1.1\r\n",
|
||||||
"CUSTOM \r\n",
|
"CUSTOM \r\n",
|
||||||
"CUSTOM /\r\n",
|
"CUSTOM HTTP/1.0\r\n",
|
||||||
"CUSTOM / \r\n",
|
"CUSTOM HTTP/1.1\r\n",
|
||||||
"CUSTOM /HTTP/1.1\r\n",
|
"CUSTOM / \n",
|
||||||
"CUSTOM \r\n",
|
"CUSTOM / HTTP/1.0\n",
|
||||||
"CUSTOM HTTP/1.0\r\n",
|
"CUSTOM / HTTP/1.1\n",
|
||||||
"CUSTOM HTTP/1.1\r\n",
|
"CUSTOM / HTTP/1.0\rA\n",
|
||||||
"CUSTOM / \n",
|
"CUSTOM / HTTP/1.1\ra\n",
|
||||||
"CUSTOM / HTTP/1.0\n",
|
"CUSTOM ? HTTP/1.1\r\n",
|
||||||
"CUSTOM / HTTP/1.1\n",
|
"CUSTOM /a?b=cHTTP/1.1\r\n",
|
||||||
"CUSTOM / HTTP/1.0\rA\n",
|
"CUSTOM /a%20bHTTP/1.1\r\n",
|
||||||
"CUSTOM / HTTP/1.1\ra\n",
|
"CUSTOM /a%20b?c=dHTTP/1.1\r\n",
|
||||||
"CUSTOM ? HTTP/1.1\r\n",
|
"CUSTOM %2F HTTP/1.1\r\n",
|
||||||
"CUSTOM /a?b=cHTTP/1.1\r\n",
|
"CUSTOM %00 HTTP/1.1\r\n",
|
||||||
"CUSTOM /a%20bHTTP/1.1\r\n",
|
// Bad HTTP Methods (invalid according to RFC)
|
||||||
"CUSTOM /a%20b?c=dHTTP/1.1\r\n",
|
"( / HTTP/1.0\r\n",
|
||||||
"CUSTOM %2F HTTP/1.1\r\n",
|
") / HTTP/1.0\r\n",
|
||||||
"CUSTOM %00 HTTP/1.1\r\n",
|
"< / HTTP/1.0\r\n",
|
||||||
// Bad HTTP Methods (invalid according to RFC)
|
"> / HTTP/1.0\r\n",
|
||||||
"( / HTTP/1.0\r\n",
|
"@ / HTTP/1.0\r\n",
|
||||||
") / HTTP/1.0\r\n",
|
", / HTTP/1.0\r\n",
|
||||||
"< / HTTP/1.0\r\n",
|
"; / HTTP/1.0\r\n",
|
||||||
"> / HTTP/1.0\r\n",
|
": / HTTP/1.0\r\n",
|
||||||
"@ / HTTP/1.0\r\n",
|
"\\ / HTTP/1.0\r\n",
|
||||||
", / HTTP/1.0\r\n",
|
"\" / HTTP/1.0\r\n",
|
||||||
"; / HTTP/1.0\r\n",
|
"/ / HTTP/1.0\r\n",
|
||||||
": / HTTP/1.0\r\n",
|
"[ / HTTP/1.0\r\n",
|
||||||
"\\ / HTTP/1.0\r\n",
|
"] / HTTP/1.0\r\n",
|
||||||
"\" / HTTP/1.0\r\n",
|
"? / HTTP/1.0\r\n",
|
||||||
"/ / HTTP/1.0\r\n",
|
"= / HTTP/1.0\r\n",
|
||||||
"[ / HTTP/1.0\r\n",
|
"{ / HTTP/1.0\r\n",
|
||||||
"] / HTTP/1.0\r\n",
|
"} / HTTP/1.0\r\n",
|
||||||
"? / HTTP/1.0\r\n",
|
"get@ / HTTP/1.0\r\n",
|
||||||
"= / HTTP/1.0\r\n",
|
"post= / HTTP/1.0\r\n",
|
||||||
"{ / HTTP/1.0\r\n",
|
};
|
||||||
"} / HTTP/1.0\r\n",
|
|
||||||
"get@ / HTTP/1.0\r\n",
|
|
||||||
"post= / HTTP/1.0\r\n",
|
|
||||||
};
|
|
||||||
|
|
||||||
var encodedNullCharInTargetRequestLines = new[]
|
public static IEnumerable<string> EncodedNullCharInTargetRequestLines => new[]
|
||||||
{
|
|
||||||
"GET /%00 HTTP/1.1\r\n",
|
|
||||||
"GET /%00%00 HTTP/1.1\r\n",
|
|
||||||
"GET /%E8%00%84 HTTP/1.1\r\n",
|
|
||||||
"GET /%E8%85%00 HTTP/1.1\r\n",
|
|
||||||
"GET /%F3%00%82%86 HTTP/1.1\r\n",
|
|
||||||
"GET /%F3%85%00%82 HTTP/1.1\r\n",
|
|
||||||
"GET /%F3%85%82%00 HTTP/1.1\r\n",
|
|
||||||
"GET /%E8%85%00 HTTP/1.1\r\n",
|
|
||||||
"GET /%E8%01%00 HTTP/1.1\r\n",
|
|
||||||
};
|
|
||||||
|
|
||||||
var nullCharInTargetRequestLines = new[]
|
|
||||||
{
|
|
||||||
"GET \0 HTTP/1.1\r\n",
|
|
||||||
"GET /\0 HTTP/1.1\r\n",
|
|
||||||
"GET /\0\0 HTTP/1.1\r\n",
|
|
||||||
"GET /%C8\0 HTTP/1.1\r\n",
|
|
||||||
};
|
|
||||||
|
|
||||||
return invalidRequestLines.Select(requestLine => new object[]
|
|
||||||
{
|
|
||||||
requestLine,
|
|
||||||
typeof(BadHttpRequestException),
|
|
||||||
$"Invalid request line: {requestLine.Replace("\r", "<0x0D>").Replace("\n", "<0x0A>")}"
|
|
||||||
})
|
|
||||||
.Concat(encodedNullCharInTargetRequestLines.Select(requestLine => new object[]
|
|
||||||
{
|
|
||||||
requestLine,
|
|
||||||
typeof(InvalidOperationException),
|
|
||||||
$"The path contains null characters."
|
|
||||||
}))
|
|
||||||
.Concat(nullCharInTargetRequestLines.Select(requestLine => new object[]
|
|
||||||
{
|
|
||||||
requestLine,
|
|
||||||
typeof(InvalidOperationException),
|
|
||||||
new InvalidOperationException().Message
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TheoryData<string> UnrecognizedHttpVersionData
|
|
||||||
{
|
{
|
||||||
get
|
"GET /%00 HTTP/1.1\r\n",
|
||||||
|
"GET /%00%00 HTTP/1.1\r\n",
|
||||||
|
"GET /%E8%00%84 HTTP/1.1\r\n",
|
||||||
|
"GET /%E8%85%00 HTTP/1.1\r\n",
|
||||||
|
"GET /%F3%00%82%86 HTTP/1.1\r\n",
|
||||||
|
"GET /%F3%85%00%82 HTTP/1.1\r\n",
|
||||||
|
"GET /%F3%85%82%00 HTTP/1.1\r\n",
|
||||||
|
"GET /%E8%85%00 HTTP/1.1\r\n",
|
||||||
|
"GET /%E8%01%00 HTTP/1.1\r\n",
|
||||||
|
};
|
||||||
|
|
||||||
|
public static IEnumerable<string> NullCharInTargetRequestLines => new[]
|
||||||
{
|
{
|
||||||
return new TheoryData<string>
|
"GET \0 HTTP/1.1\r\n",
|
||||||
{
|
"GET /\0 HTTP/1.1\r\n",
|
||||||
"H",
|
"GET /\0\0 HTTP/1.1\r\n",
|
||||||
"HT",
|
"GET /%C8\0 HTTP/1.1\r\n",
|
||||||
"HTT",
|
};
|
||||||
"HTTP",
|
|
||||||
"HTTP/",
|
public static TheoryData<string> UnrecognizedHttpVersionData => new TheoryData<string>
|
||||||
"HTTP/1",
|
{
|
||||||
"HTTP/1.",
|
"H",
|
||||||
"http/1.0",
|
"HT",
|
||||||
"http/1.1",
|
"HTT",
|
||||||
"HTTP/1.1 ",
|
"HTTP",
|
||||||
"HTTP/1.0a",
|
"HTTP/",
|
||||||
"HTTP/1.0ab",
|
"HTTP/1",
|
||||||
"HTTP/1.1a",
|
"HTTP/1.",
|
||||||
"HTTP/1.1ab",
|
"http/1.0",
|
||||||
"HTTP/1.2",
|
"http/1.1",
|
||||||
"HTTP/3.0",
|
"HTTP/1.1 ",
|
||||||
"hello",
|
"HTTP/1.0a",
|
||||||
"8charact",
|
"HTTP/1.0ab",
|
||||||
};
|
"HTTP/1.1a",
|
||||||
}
|
"HTTP/1.1ab",
|
||||||
}
|
"HTTP/1.2",
|
||||||
|
"HTTP/3.0",
|
||||||
|
"hello",
|
||||||
|
"8charact",
|
||||||
|
};
|
||||||
|
|
||||||
public static IEnumerable<object[]> InvalidRequestHeaderData
|
public static IEnumerable<object[]> InvalidRequestHeaderData
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue