Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

Commit

Permalink
Expose settable properties directly in IHttpMinRequestBodyDataRateFea…
Browse files Browse the repository at this point in the history
…ture.
  • Loading branch information
Cesar Blum Silveira committed Jun 24, 2017
1 parent da57fef commit 5c63a58
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 100 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// 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;

namespace Microsoft.AspNetCore.Server.Kestrel.Core.Features
{
/// <summary>
Expand All @@ -10,9 +12,14 @@ public interface IHttpMinRequestBodyDataRateFeature
{
/// <summary>
/// The minimum data rate in bytes/second at which the request body should be received.
/// Setting this property to null indicates no minimum data rate should be enforced.
/// Setting this property to zero effectively means no minimum data rate should be enforced.
/// This limit has no effect on upgraded connections which are always unlimited.
/// </summary>
MinimumDataRate MinimumDataRate { get; set; }
double BytesPerSecond { get; set; }

/// <summary>
/// The amount of time to delay enforcement of the minimum data rate.
/// </summary>
TimeSpan GracePeriod { get; set; }
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,32 @@ string IHttpRequestIdentifierFeature.TraceIdentifier
}
}

MinimumDataRate IHttpMinRequestBodyDataRateFeature.MinimumDataRate
double IHttpMinRequestBodyDataRateFeature.BytesPerSecond
{
get => MinRequestBodyDataRate;
set => MinRequestBodyDataRate = value;
get => MinRequestBodyDataRate.BytesPerSecond;
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value), CoreStrings.NonNegativeNumberRequired);
}

MinRequestBodyDataRate.BytesPerSecond = value;
}
}

TimeSpan IHttpMinRequestBodyDataRateFeature.GracePeriod
{
get => MinRequestBodyDataRate.GracePeriod;
set
{
if (value < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(value), CoreStrings.NonNegativeTimeSpanRequired);
}

MinRequestBodyDataRate.GracePeriod = value;
}
}

object IFeatureCollection.this[Type key]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ private CancellationTokenSource RequestAbortedSource

protected FrameResponseHeaders FrameResponseHeaders { get; } = new FrameResponseHeaders();

public MinimumDataRate MinRequestBodyDataRate { get; set; }
public KestrelServerLimits.MinimumDataRate MinRequestBodyDataRate { get; } = new KestrelServerLimits.MinimumDataRate();

public void InitializeStreams(MessageBody messageBody)
{
Expand Down Expand Up @@ -379,7 +379,8 @@ public void Reset()
_responseBytesWritten = 0;
_requestCount++;

MinRequestBodyDataRate = ServerOptions.Limits.MinRequestBodyDataRate;
MinRequestBodyDataRate.BytesPerSecond = ServerOptions.Limits.MinRequestBodyDataRate.BytesPerSecond;
MinRequestBodyDataRate.GracePeriod = ServerOptions.Limits.MinRequestBodyDataRate.GracePeriod;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,52 @@ public long? MaxConcurrentUpgradedConnections

/// <summary>
/// Gets or sets the request body minimum data rate in bytes/second.
/// Setting this property to null indicates no minimum data rate should be enforced.
/// This limit has no effect on upgraded connections which are always unlimited.
/// This can be overridden per-request via <see cref="IHttpMinRequestBodyDataRateFeature"/>.
/// This limit has no effect on upgraded connections.
/// This limit can be overridden per-request via <see cref="IHttpMinRequestBodyDataRateFeature"/>.
/// </summary>
/// <remarks>
/// Defaults to 1 byte/second with a 5 second grace period.
/// Defaults to 1 byte/second with a 5 second grace period during which the minimum data rate is not enforced.
/// </remarks>
public MinimumDataRate MinRequestBodyDataRate { get; set; } = new MinimumDataRate(bytesPerSecond: 1, gracePeriod: TimeSpan.FromSeconds(5));
public MinimumDataRate MinRequestBodyDataRate { get; } = new MinimumDataRate { BytesPerSecond = 1, GracePeriod = TimeSpan.FromSeconds(5) };

public class MinimumDataRate
{
private double _bytesPerSecond;
private TimeSpan _gracePeriod;

/// <summary>
/// The minimum rate in bytes/second at which data should be processed.
/// </summary>
public double BytesPerSecond
{
get => _bytesPerSecond;
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value), CoreStrings.NonNegativeNumberRequired);
}

_bytesPerSecond = value;
}
}

/// <summary>
/// The amount of time to delay enforcement of <see cref="MinimumDataRate" />.
/// </summary>
public TimeSpan GracePeriod
{
get => _gracePeriod;
set
{
if (value < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(value), CoreStrings.NonNegativeTimeSpanRequired);
}

_gracePeriod = value;
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public void TimesOutWhenRequestBodyDoesNotSatisfyMinimumDataRate()
var bytesPerSecond = 100;
var gracePeriod = TimeSpan.FromSeconds(5);

_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate =
new MinimumDataRate(bytesPerSecond: bytesPerSecond, gracePeriod: gracePeriod);
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.BytesPerSecond = bytesPerSecond;
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.GracePeriod = gracePeriod;

var mockLogger = new Mock<IKestrelTrace>();
_frameConnectionContext.ServiceContext.Log = mockLogger.Object;
Expand Down Expand Up @@ -88,8 +88,8 @@ public void RequestBodyMinimumDataRateNotEnforcedDuringGracePeriod()
var bytesPerSecond = 100;
var gracePeriod = TimeSpan.FromSeconds(2);

_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate =
new MinimumDataRate(bytesPerSecond: bytesPerSecond, gracePeriod: gracePeriod);
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.BytesPerSecond = bytesPerSecond;
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.GracePeriod = gracePeriod;

var mockLogger = new Mock<IKestrelTrace>();
_frameConnectionContext.ServiceContext.Log = mockLogger.Object;
Expand Down Expand Up @@ -130,8 +130,8 @@ public void RequestBodyDataRateIsAveragedOverTimeSpentReadingRequestBody()
var bytesPerSecond = 100;
var gracePeriod = TimeSpan.FromSeconds(1);

_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate =
new MinimumDataRate(bytesPerSecond: bytesPerSecond, gracePeriod: gracePeriod);
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.BytesPerSecond = bytesPerSecond;
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.GracePeriod = gracePeriod;

var mockLogger = new Mock<IKestrelTrace>();
_frameConnectionContext.ServiceContext.Log = mockLogger.Object;
Expand Down Expand Up @@ -197,8 +197,9 @@ public void RequestBodyDataRateNotComputedOnPausedTime()
var requestBodyTimeout = TimeSpan.FromSeconds(5);
var systemClock = new MockSystemClock();

_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate =
new MinimumDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.Zero);
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.BytesPerSecond = 100;
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.GracePeriod = TimeSpan.Zero;

_frameConnectionContext.ServiceContext.SystemClock = systemClock;

var mockLogger = new Mock<IKestrelTrace>();
Expand Down Expand Up @@ -265,8 +266,9 @@ public void ReadTimingNotPausedWhenResumeCalledBeforeNextTick()
{
var systemClock = new MockSystemClock();

_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate =
new MinimumDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.Zero);
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.BytesPerSecond = 100;
_frameConnectionContext.ServiceContext.ServerOptions.Limits.MinRequestBodyDataRate.GracePeriod = TimeSpan.Zero;

_frameConnectionContext.ServiceContext.SystemClock = systemClock;

var mockLogger = new Mock<IKestrelTrace>();
Expand Down
56 changes: 37 additions & 19 deletions test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests/FrameTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,13 @@ public void ResetResetsTraceIdentifier()
[Fact]
public void ResetResetsMinRequestBodyDataRate()
{
_frame.MinRequestBodyDataRate = new MinimumDataRate(bytesPerSecond: 1, gracePeriod: TimeSpan.Zero);
_frame.MinRequestBodyDataRate.BytesPerSecond = 1;
_frame.MinRequestBodyDataRate.GracePeriod = TimeSpan.Zero;

_frame.Reset();

Assert.Equal(_serviceContext.ServerOptions.Limits.MinRequestBodyDataRate, _frame.MinRequestBodyDataRate);
Assert.Equal(_serviceContext.ServerOptions.Limits.MinRequestBodyDataRate.BytesPerSecond, _frame.MinRequestBodyDataRate.BytesPerSecond);
Assert.Equal(_serviceContext.ServerOptions.Limits.MinRequestBodyDataRate.GracePeriod, _frame.MinRequestBodyDataRate.GracePeriod);
}

[Fact]
Expand Down Expand Up @@ -255,11 +257,36 @@ public async Task ThrowsWhenOnStartingIsSetAfterResponseStarted()

[Theory]
[MemberData(nameof(MinRequestBodyDataRateData))]
public void ConfiguringIHttpMinRequestBodyDataRateFeatureSetsMinRequestBodyDateRate(MinimumDataRate minimumDataRate)
public void ConfiguringIHttpMinRequestBodyDataRateFeatureSetsMinRequestBodyDateRate(double bytesPerSecond, TimeSpan gracePeriod)
{
((IFeatureCollection)_frame).Get<IHttpMinRequestBodyDataRateFeature>().MinimumDataRate = minimumDataRate;
var feature = ((IFeatureCollection)_frame).Get<IHttpMinRequestBodyDataRateFeature>();
feature.BytesPerSecond = bytesPerSecond;
feature.GracePeriod = gracePeriod;

Assert.Same(minimumDataRate, _frame.MinRequestBodyDataRate);
Assert.Equal(bytesPerSecond, _frame.MinRequestBodyDataRate.BytesPerSecond);
Assert.Equal(gracePeriod, _frame.MinRequestBodyDataRate.GracePeriod);
}

[Theory]
[InlineData(double.MinValue)]
public void ThrowsWhenMinRequestBodyDataRateBytesPerSecondIsSetToANegativeValue(double value)
{
var exception = Assert.Throws<ArgumentOutOfRangeException>(() =>
((IFeatureCollection)_frame).Get<IHttpMinRequestBodyDataRateFeature>().BytesPerSecond = value);

Assert.Equal("value", exception.ParamName);
Assert.StartsWith(CoreStrings.NonNegativeNumberRequired, exception.Message);
}

[Theory]
[MemberData(nameof(MinRequestBodyDataRateGracePeriodInvalidData))]
public void ThrowsWhenMinRequestBodyDataRateGracePeriodIsSetToANegativeValue(TimeSpan value)
{
var exception = Assert.Throws<ArgumentOutOfRangeException>(() =>
((IFeatureCollection)_frame).Get<IHttpMinRequestBodyDataRateFeature>().GracePeriod = value);

Assert.Equal("value", exception.ParamName);
Assert.StartsWith(CoreStrings.NonNegativeTimeSpanRequired, exception.Message);
}

[Fact]
Expand Down Expand Up @@ -863,25 +890,16 @@ public static TheoryData<string> QueryStringWithNullCharData
}
}

public static TheoryData<TimeSpan> RequestBodyTimeoutDataValid => new TheoryData<TimeSpan>
public static TheoryData<double, TimeSpan> MinRequestBodyDataRateData => new TheoryData<double, TimeSpan>
{
TimeSpan.FromTicks(1),
TimeSpan.MaxValue,
Timeout.InfiniteTimeSpan,
TimeSpan.FromMilliseconds(-1) // Same as Timeout.InfiniteTimeSpan
{ 0, TimeSpan.Zero },
{ 1, TimeSpan.Zero }
};

public static TheoryData<TimeSpan> RequestBodyTimeoutDataInvalid => new TheoryData<TimeSpan>
public static TheoryData<TimeSpan> MinRequestBodyDataRateGracePeriodInvalidData => new TheoryData<TimeSpan>
{
TimeSpan.MinValue,
TimeSpan.FromTicks(-1),
TimeSpan.Zero
};

public static TheoryData<MinimumDataRate> MinRequestBodyDataRateData => new TheoryData<MinimumDataRate>
{
null,
new MinimumDataRate(bytesPerSecond: 1, gracePeriod: TimeSpan.Zero)
TimeSpan.FromTicks(-1)
};

private class RequestHeadersWrapper : IHeaderDictionary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,41 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public class MinimumDataRateTests
{
[Theory]
[InlineData(0)]
[InlineData(double.Epsilon)]
[InlineData(double.MaxValue)]
public void BytesPerSecondValid(double value)
{
Assert.Equal(value, new MinimumDataRate(bytesPerSecond: value, gracePeriod: TimeSpan.Zero).BytesPerSecond);
Assert.Equal(value, new KestrelServerLimits.MinimumDataRate { BytesPerSecond = value, GracePeriod = TimeSpan.Zero }.BytesPerSecond);
}

[Theory]
[InlineData(double.MinValue)]
[InlineData(0)]
[InlineData(-double.Epsilon)]
public void BytesPerSecondInvalid(double value)
{
var exception = Assert.Throws<ArgumentOutOfRangeException>(() => new MinimumDataRate(bytesPerSecond: value, gracePeriod: TimeSpan.Zero));
var exception = Assert.Throws<ArgumentOutOfRangeException>(() =>
new KestrelServerLimits.MinimumDataRate { BytesPerSecond = value, GracePeriod = TimeSpan.Zero });

Assert.Equal("bytesPerSecond", exception.ParamName);
Assert.StartsWith(CoreStrings.PositiveNumberRequired, exception.Message);
Assert.Equal("value", exception.ParamName);
Assert.StartsWith(CoreStrings.NonNegativeNumberRequired, exception.Message);
}

[Theory]
[MemberData(nameof(GracePeriodValidData))]
public void GracePeriodValid(TimeSpan value)
{
Assert.Equal(value, new MinimumDataRate(bytesPerSecond: 1, gracePeriod: value).GracePeriod);
Assert.Equal(value, new KestrelServerLimits.MinimumDataRate { BytesPerSecond = 1, GracePeriod = value }.GracePeriod);
}

[Theory]
[MemberData(nameof(GracePeriodInvalidData))]
public void GracePeriodInvalid(TimeSpan value)
{
var exception = Assert.Throws<ArgumentOutOfRangeException>(() => new MinimumDataRate(bytesPerSecond: 1, gracePeriod: value));
var exception = Assert.Throws<ArgumentOutOfRangeException>(() =>
new KestrelServerLimits.MinimumDataRate { BytesPerSecond = 1, GracePeriod = value });

Assert.Equal("gracePeriod", exception.ParamName);
Assert.Equal("value", exception.ParamName);
Assert.StartsWith(CoreStrings.NonNegativeTimeSpanRequired, exception.Message);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,10 @@ private TestServer CreateServer(CancellationToken longRunningCt, CancellationTok
Limits =
{
KeepAliveTimeout = KeepAliveTimeout,
MinRequestBodyDataRate = null
MinRequestBodyDataRate =
{
BytesPerSecond = 0
}
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ private static IWebHost StartWebHost(long? maxRequestBufferSize,
options.Limits.MaxRequestHeadersTotalSize = (int)maxRequestBufferSize;
}
options.Limits.MinRequestBodyDataRate = null;
options.Limits.MinRequestBodyDataRate.BytesPerSecond = 0;
})
.UseContentRoot(Directory.GetCurrentDirectory())
.Configure(app => app.Run(async context =>
Expand Down
Loading

0 comments on commit 5c63a58

Please sign in to comment.