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
Show file tree
Hide file tree
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
Expand Up @@ -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" />
Expand Down Expand Up @@ -58,6 +70,7 @@
<ItemGroup>
<Compile Include="IpAddressUtilTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ThrottlingMiddlewareTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
Expand Down
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" />
Expand Down
11 changes: 4 additions & 7 deletions WebApiThrottle/ThrottlingMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down