157 lines
5.5 KiB
C#
157 lines
5.5 KiB
C#
// 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.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
|
using Microsoft.AspNetCore.Testing;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|
{
|
|
public class RequestHeaderLimitsTests
|
|
{
|
|
[Theory]
|
|
[InlineData(0, 1)]
|
|
[InlineData(0, 1337)]
|
|
[InlineData(1, 0)]
|
|
[InlineData(1, 1)]
|
|
[InlineData(1, 1337)]
|
|
[InlineData(5, 0)]
|
|
[InlineData(5, 1)]
|
|
[InlineData(5, 1337)]
|
|
public async Task ServerAcceptsRequestWithHeaderTotalSizeWithinLimit(int headerCount, int extraLimit)
|
|
{
|
|
var headers = MakeHeaders(headerCount);
|
|
|
|
using (var server = CreateServer(maxRequestHeadersTotalSize: headers.Length + extraLimit))
|
|
{
|
|
using (var connection = new TestConnection(server.Port))
|
|
{
|
|
await connection.Send($"GET / HTTP/1.1\r\n{headers}\r\n");
|
|
await connection.ReceiveEnd(
|
|
"HTTP/1.1 200 OK",
|
|
$"Date: {server.Context.DateHeaderValue}",
|
|
"Transfer-Encoding: chunked",
|
|
"",
|
|
"c",
|
|
"hello, world",
|
|
"0",
|
|
"",
|
|
"");
|
|
}
|
|
}
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0, 1)]
|
|
[InlineData(0, 1337)]
|
|
[InlineData(1, 1)]
|
|
[InlineData(1, 2)]
|
|
[InlineData(1, 1337)]
|
|
[InlineData(5, 5)]
|
|
[InlineData(5, 6)]
|
|
[InlineData(5, 1337)]
|
|
public async Task ServerAcceptsRequestWithHeaderCountWithinLimit(int headerCount, int maxHeaderCount)
|
|
{
|
|
var headers = MakeHeaders(headerCount);
|
|
|
|
using (var server = CreateServer(maxRequestHeaderCount: maxHeaderCount))
|
|
{
|
|
using (var connection = new TestConnection(server.Port))
|
|
{
|
|
await connection.Send($"GET / HTTP/1.1\r\n{headers}\r\n");
|
|
await connection.ReceiveEnd(
|
|
"HTTP/1.1 200 OK",
|
|
$"Date: {server.Context.DateHeaderValue}",
|
|
"Transfer-Encoding: chunked",
|
|
"",
|
|
"c",
|
|
"hello, world",
|
|
"0",
|
|
"",
|
|
"");
|
|
}
|
|
}
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1)]
|
|
[InlineData(5)]
|
|
public async Task ServerRejectsRequestWithHeaderTotalSizeOverLimit(int headerCount)
|
|
{
|
|
var headers = MakeHeaders(headerCount);
|
|
|
|
using (var server = CreateServer(maxRequestHeadersTotalSize: headers.Length - 1))
|
|
{
|
|
using (var connection = new TestConnection(server.Port))
|
|
{
|
|
await connection.SendAll($"GET / HTTP/1.1\r\n{headers}\r\n");
|
|
await connection.ReceiveForcedEnd(
|
|
"HTTP/1.1 431 Request Header Fields Too Large",
|
|
"Connection: close",
|
|
$"Date: {server.Context.DateHeaderValue}",
|
|
"Content-Length: 0",
|
|
"",
|
|
"");
|
|
}
|
|
}
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(2, 1)]
|
|
[InlineData(5, 1)]
|
|
[InlineData(5, 4)]
|
|
public async Task ServerRejectsRequestWithHeaderCountOverLimit(int headerCount, int maxHeaderCount)
|
|
{
|
|
var headers = MakeHeaders(headerCount);
|
|
|
|
using (var server = CreateServer(maxRequestHeaderCount: maxHeaderCount))
|
|
{
|
|
using (var connection = new TestConnection(server.Port))
|
|
{
|
|
await connection.SendAll($"GET / HTTP/1.1\r\n{headers}\r\n");
|
|
await connection.ReceiveForcedEnd(
|
|
"HTTP/1.1 431 Request Header Fields Too Large",
|
|
"Connection: close",
|
|
$"Date: {server.Context.DateHeaderValue}",
|
|
"Content-Length: 0",
|
|
"",
|
|
"");
|
|
}
|
|
}
|
|
}
|
|
|
|
private static string MakeHeaders(int count)
|
|
{
|
|
const string host = "Host:\r\n";
|
|
if (count <= 1) return host;
|
|
|
|
return string.Join("", new[] { host }
|
|
.Concat(Enumerable
|
|
.Range(0, count -1)
|
|
.Select(i => $"Header-{i}: value{i}\r\n")));
|
|
}
|
|
|
|
private TestServer CreateServer(int? maxRequestHeaderCount = null, int? maxRequestHeadersTotalSize = null)
|
|
{
|
|
var options = new KestrelServerOptions { AddServerHeader = false };
|
|
|
|
if (maxRequestHeaderCount.HasValue)
|
|
{
|
|
options.Limits.MaxRequestHeaderCount = maxRequestHeaderCount.Value;
|
|
}
|
|
|
|
if (maxRequestHeadersTotalSize.HasValue)
|
|
{
|
|
options.Limits.MaxRequestHeadersTotalSize = maxRequestHeadersTotalSize.Value;
|
|
}
|
|
|
|
return new TestServer(async httpContext => await httpContext.Response.WriteAsync("hello, world"), new TestServiceContext
|
|
{
|
|
ServerOptions = options
|
|
});
|
|
}
|
|
}
|
|
} |