Browse Source

Api blocking limits.

pull/492/head
Sebastian 6 years ago
parent
commit
a42a9762b1
  1. 2
      backend/src/Squidex.Domain.Apps.Entities/Apps/Services/IAppLimitsPlan.cs
  2. 2
      backend/src/Squidex.Domain.Apps.Entities/Apps/Services/Implementations/ConfigAppLimitsPlan.cs
  3. 8
      backend/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs
  4. 7
      backend/src/Squidex.Infrastructure/Assets/ResizeOptions.cs
  5. 2
      backend/src/Squidex.Web/Pipeline/ApiCostsFilter.cs
  6. 2
      backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
  7. 7
      backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetQuery.cs
  8. 24
      backend/tests/Squidex.Web.Tests/Pipeline/ApiCostsFilterTests.cs

2
backend/src/Squidex.Domain.Apps.Entities/Apps/Services/IAppLimitsPlan.cs

@ -19,6 +19,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Services
string? YearlyId { get; } string? YearlyId { get; }
long BlockingApiCalls { get; }
long MaxApiCalls { get; } long MaxApiCalls { get; }
long MaxAssetSize { get; } long MaxAssetSize { get; }

2
backend/src/Squidex.Domain.Apps.Entities/Apps/Services/Implementations/ConfigAppLimitsPlan.cs

@ -19,6 +19,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Services.Implementations
public string? YearlyId { get; set; } public string? YearlyId { get; set; }
public long BlockingApiCalls { get; set; }
public long MaxApiCalls { get; set; } public long MaxApiCalls { get; set; }
public long MaxAssetSize { get; set; } public long MaxAssetSize { get; set; }

8
backend/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs

@ -25,16 +25,16 @@ namespace Squidex.Infrastructure.Assets.ImageSharp
return Task.Run(() => return Task.Run(() =>
{ {
var w = options.Width ?? 0; if (!options.IsValid)
var h = options.Height ?? 0;
if (w <= 0 && h <= 0 && !options.Quality.HasValue)
{ {
source.CopyTo(destination); source.CopyTo(destination);
return; return;
} }
var w = options.Width ?? 0;
var h = options.Height ?? 0;
using (var sourceImage = Image.Load(source, out var format)) using (var sourceImage = Image.Load(source, out var format))
{ {
var encoder = Configuration.Default.ImageFormatsManager.FindEncoder(format); var encoder = Configuration.Default.ImageFormatsManager.FindEncoder(format);

7
backend/src/Squidex.Infrastructure/Assets/ResizeOptions.cs

@ -11,6 +11,8 @@ namespace Squidex.Infrastructure.Assets
{ {
public sealed class ResizeOptions public sealed class ResizeOptions
{ {
public ResizeMode Mode { get; set; }
public int? Width { get; set; } public int? Width { get; set; }
public int? Height { get; set; } public int? Height { get; set; }
@ -21,7 +23,10 @@ namespace Squidex.Infrastructure.Assets
public float? FocusY { get; set; } public float? FocusY { get; set; }
public ResizeMode Mode { get; set; } public bool IsValid
{
get { return Width > 0 || Height > 0 || Quality > 0; }
}
public override string ToString() public override string ToString()
{ {

2
backend/src/Squidex.Web/Pipeline/ApiCostsFilter.cs

@ -73,7 +73,7 @@ namespace Squidex.Web.Pipeline
var usage = await usageTracker.GetMonthlyCallsAsync(appId, DateTime.Today); var usage = await usageTracker.GetMonthlyCallsAsync(appId, DateTime.Today);
if (plan.MaxApiCalls >= 0 && usage > plan.MaxApiCalls * 1.1) if (plan.BlockingApiCalls >= 0 && usage > plan.BlockingApiCalls)
{ {
context.Result = new StatusCodeResult(429); context.Result = new StatusCodeResult(429);
return; return;

2
backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs

@ -138,7 +138,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
{ {
var resizeOptions = query.ToResizeOptions(asset); var resizeOptions = query.ToResizeOptions(asset);
if (asset.Type == AssetType.Image && resizeOptions != null) if (asset.Type == AssetType.Image && resizeOptions.IsValid)
{ {
var resizedAsset = $"{asset.Id}_{asset.FileVersion}_{resizeOptions}"; var resizedAsset = $"{asset.Id}_{asset.FileVersion}_{resizeOptions}";

7
backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetQuery.cs

@ -81,15 +81,10 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models
[FromQuery(Name = "force")] [FromQuery(Name = "force")]
public bool ForceResize { get; set; } public bool ForceResize { get; set; }
public ResizeOptions? ToResizeOptions(IAssetEntity asset) public ResizeOptions ToResizeOptions(IAssetEntity asset)
{ {
Guard.NotNull(asset); Guard.NotNull(asset);
if (!Width.HasValue && !Height.HasValue && !Quality.HasValue)
{
return null;
}
var result = SimpleMapper.Map(this, new ResizeOptions()); var result = SimpleMapper.Map(this, new ResizeOptions());
var (x, y) = GetFocusPoint(asset); var (x, y) = GetFocusPoint(asset);

24
backend/tests/Squidex.Web.Tests/Pipeline/ApiCostsFilterTests.cs

@ -36,7 +36,7 @@ namespace Squidex.Web.Pipeline
private readonly HttpContext httpContext = new DefaultHttpContext(); private readonly HttpContext httpContext = new DefaultHttpContext();
private readonly ActionExecutionDelegate next; private readonly ActionExecutionDelegate next;
private readonly ApiCostsFilter sut; private readonly ApiCostsFilter sut;
private long apiCallsMax; private long apiCallsBlocking;
private long apiCallsCurrent; private long apiCallsCurrent;
private bool isNextCalled; private bool isNextCalled;
@ -57,8 +57,8 @@ namespace Squidex.Web.Pipeline
A.CallTo(() => appPlansProvider.GetPlanForApp(appEntity)) A.CallTo(() => appPlansProvider.GetPlanForApp(appEntity))
.Returns((appPlan, "free")); .Returns((appPlan, "free"));
A.CallTo(() => appPlan.MaxApiCalls) A.CallTo(() => appPlan.BlockingApiCalls)
.ReturnsLazily(x => apiCallsMax); .ReturnsLazily(x => apiCallsBlocking);
A.CallTo(() => usageTracker.GetMonthlyCallsAsync(A<string>._, DateTime.Today)) A.CallTo(() => usageTracker.GetMonthlyCallsAsync(A<string>._, DateTime.Today))
.ReturnsLazily(x => Task.FromResult(apiCallsCurrent)); .ReturnsLazily(x => Task.FromResult(apiCallsCurrent));
@ -74,14 +74,14 @@ namespace Squidex.Web.Pipeline
} }
[Fact] [Fact]
public async Task Should_return_429_status_code_if_max_calls_over_limit() public async Task Should_return_429_status_code_if_max_calls_over_blocking_limit()
{ {
sut.FilterDefinition = new ApiCostsAttribute(1); sut.FilterDefinition = new ApiCostsAttribute(1);
SetupApp(); SetupApp();
apiCallsCurrent = 1000; apiCallsCurrent = 1000;
apiCallsMax = 600; apiCallsBlocking = 600;
await sut.OnActionExecutionAsync(actionContext, next); await sut.OnActionExecutionAsync(actionContext, next);
@ -100,7 +100,7 @@ namespace Squidex.Web.Pipeline
SetupApp(); SetupApp();
apiCallsCurrent = 1000; apiCallsCurrent = 1000;
apiCallsMax = 1600; apiCallsBlocking = 1600;
await sut.OnActionExecutionAsync(actionContext, next); await sut.OnActionExecutionAsync(actionContext, next);
@ -111,21 +111,21 @@ namespace Squidex.Web.Pipeline
} }
[Fact] [Fact]
public async Task Should_allow_small_buffer() public async Task Should_not_allow_small_buffer()
{ {
sut.FilterDefinition = new ApiCostsAttribute(13); sut.FilterDefinition = new ApiCostsAttribute(13);
SetupApp(); SetupApp();
apiCallsCurrent = 1099; apiCallsCurrent = 1099;
apiCallsMax = 1000; apiCallsBlocking = 1000;
await sut.OnActionExecutionAsync(actionContext, next); await sut.OnActionExecutionAsync(actionContext, next);
Assert.True(isNextCalled); Assert.False(isNextCalled);
A.CallTo(() => usageTracker.TrackAsync(A<string>._, A<string>._, 13, A<double>._)) A.CallTo(() => usageTracker.TrackAsync(A<string>._, A<string>._, 13, A<double>._))
.MustHaveHappened(); .MustNotHaveHappened();
} }
[Fact] [Fact]
@ -136,7 +136,7 @@ namespace Squidex.Web.Pipeline
SetupApp(); SetupApp();
apiCallsCurrent = 1000; apiCallsCurrent = 1000;
apiCallsMax = 600; apiCallsBlocking = 600;
await sut.OnActionExecutionAsync(actionContext, next); await sut.OnActionExecutionAsync(actionContext, next);
@ -152,7 +152,7 @@ namespace Squidex.Web.Pipeline
sut.FilterDefinition = new ApiCostsAttribute(1); sut.FilterDefinition = new ApiCostsAttribute(1);
apiCallsCurrent = 1000; apiCallsCurrent = 1000;
apiCallsMax = 600; apiCallsBlocking = 600;
await sut.OnActionExecutionAsync(actionContext, next); await sut.OnActionExecutionAsync(actionContext, next);

Loading…
Cancel
Save