Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Don't use OnSendingHeaders #92

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions WebApiThrottle.Tests/ThrottlingMiddlewareTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Owin;
using Moq;
using Xunit;

namespace WebApiThrottle.Tests
{
public class ThrottlingMiddlewareTests
{
private static IOwinContext CreateMockContext()
{
var context = Mock.Of<IOwinContext>();

Mock.Get(context).SetupGet(x => x.Request).Returns(Mock.Of<IOwinRequest>());
Mock.Get(context.Request).SetupAllProperties();
Mock.Get(context.Request).SetupGet(x => x.Headers).Returns(Mock.Of<IHeaderDictionary>());
Mock.Get(context.Request.Headers).SetupGet(x => x.Keys).Returns(new List<string>());
context.Request.RemoteIpAddress = "127.0.0.1";
Mock.Get(context.Request).SetupGet(x => x.Uri).Returns(new Uri($"http://{context.Request.RemoteIpAddress}"));

Mock.Get(context).SetupGet(x => x.Response).Returns(Mock.Of<IOwinResponse>());
Mock.Get(context.Response).SetupAllProperties();
Mock.Get(context.Response).SetupGet(x => x.Headers).Returns(Mock.Of<IHeaderDictionary>());
Mock.Get(context.Response.Headers).Setup(x => x.Add("Retry-After", It.IsAny<string[]>()));
context.Response.StatusCode = 200;

return context;
}

private static ThrottlingMiddleware CreateThrottlingMiddleware()
{
return new ThrottlingMiddleware(
new DummyMiddleware(null),
new ThrottlePolicy(1) {IpThrottling = true},
new PolicyMemoryCacheRepository(),
new MemoryCacheRepository(),
null,
null);
}


[Fact]
public void When_RateIsExceeded_Should_SetStatusCodeSoItsAvailableToMiddlewareFurtherDownTheStack()
{
var context = CreateMockContext();

var throttlingMiddleware = CreateThrottlingMiddleware();

throttlingMiddleware.Invoke(context).Wait();
throttlingMiddleware.Invoke(context).Wait();

Assert.Equal(429, context.Response.StatusCode);
}

[Fact]
public void When_RateIsNotExceeded_Should_NotSetStatusCode()
{
var context = CreateMockContext();

CreateThrottlingMiddleware().Invoke(context).Wait();

Assert.Equal(200, context.Response.StatusCode);
}
}

internal class DummyMiddleware : OwinMiddleware
{
public DummyMiddleware(OwinMiddleware next) : base(next)
{
}

public override async Task Invoke(IOwinContext context)
{
}
}
}
13 changes: 13 additions & 0 deletions WebApiThrottle.Tests/WebApiThrottle.Tests.csproj
Original file line number Diff line number Diff line change
@@ -30,6 +30,18 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.7.1.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.7.1\lib\net45\Moq.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
@@ -58,6 +70,7 @@
<ItemGroup>
<Compile Include="IpAddressUtilTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ThrottlingMiddlewareTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
4 changes: 4 additions & 0 deletions WebApiThrottle.Tests/packages.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Castle.Core" version="4.0.0" targetFramework="net452" />
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net452" />
<package id="Moq" version="4.7.1" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net452" />
<package id="xunit" version="2.1.0" targetFramework="net452" />
<package id="xunit.abstractions" version="2.0.0" targetFramework="net452" />
<package id="xunit.assert" version="2.1.0" targetFramework="net452" />
11 changes: 4 additions & 7 deletions WebApiThrottle/ThrottlingMiddleware.cs
Original file line number Diff line number Diff line change
@@ -196,13 +196,10 @@ public override async Task Invoke(IOwinContext context)
: "API calls quota exceeded! maximum admitted {0} per {1}.";

// break execution
response.OnSendingHeaders(state =>
{
var resp = (OwinResponse)state;
resp.Headers.Add("Retry-After", new string[] { core.RetryAfterFrom(throttleCounter.Timestamp, rateLimitPeriod) });
resp.StatusCode = (int)QuotaExceededResponseCode;
resp.ReasonPhrase = string.Format(message, rateLimit, rateLimitPeriod);
}, response);
response.StatusCode = (int)QuotaExceededResponseCode;
response.ReasonPhrase = string.Format(message, rateLimit, rateLimitPeriod);

response.Headers.Add("Retry-After", new[] { core.RetryAfterFrom(throttleCounter.Timestamp, rateLimitPeriod) });

return;
}