mirror of https://github.com/Squidex/squidex.git
15 changed files with 110 additions and 129 deletions
@ -0,0 +1,76 @@ |
|||||
|
// ==========================================================================
|
||||
|
// ApiCostsFilter.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Diagnostics; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Filters; |
||||
|
using Squidex.Domain.Apps.Read.Apps.Services; |
||||
|
using Squidex.Infrastructure.UsageTracking; |
||||
|
|
||||
|
namespace Squidex.Pipeline |
||||
|
{ |
||||
|
public sealed class ApiCostsFilter : IAsyncActionFilter, IFilterContainer |
||||
|
{ |
||||
|
private readonly IAppPlansProvider appPlanProvider; |
||||
|
private readonly IUsageTracker usageTracker; |
||||
|
|
||||
|
public ApiCostsFilter(IAppPlansProvider appPlanProvider, IUsageTracker usageTracker) |
||||
|
{ |
||||
|
this.appPlanProvider = appPlanProvider; |
||||
|
|
||||
|
this.usageTracker = usageTracker; |
||||
|
} |
||||
|
|
||||
|
IFilterMetadata IFilterContainer.FilterDefinition { get; set; } |
||||
|
|
||||
|
public ApiCostsAttribute FilterDefinition |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return (ApiCostsAttribute)((IFilterContainer)this).FilterDefinition; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) |
||||
|
{ |
||||
|
var appFeature = context.HttpContext.Features.Get<IAppFeature>(); |
||||
|
|
||||
|
if (appFeature?.App != null && FilterDefinition.Weight > 0) |
||||
|
{ |
||||
|
var stopWatch = Stopwatch.StartNew(); |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
var plan = appPlanProvider.GetPlanForApp(appFeature.App); |
||||
|
|
||||
|
var usage = await usageTracker.GetMonthlyCalls(appFeature.App.Id.ToString(), DateTime.Today); |
||||
|
|
||||
|
if (plan.MaxApiCalls >= 0 && (usage * 1.1) > plan.MaxApiCalls) |
||||
|
{ |
||||
|
context.Result = new StatusCodeResult(429); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
await next(); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
stopWatch.Stop(); |
||||
|
|
||||
|
await usageTracker.TrackAsync(appFeature.App.Id.ToString(), FilterDefinition.Weight, stopWatch.ElapsedMilliseconds); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
await next(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,22 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// AppFeature.cs
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex Group
|
|
||||
// All rights reserved.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using Squidex.Domain.Apps.Read.Apps; |
|
||||
|
|
||||
namespace Squidex.Pipeline |
|
||||
{ |
|
||||
public sealed class AppFeature : IAppFeature |
|
||||
{ |
|
||||
public IAppEntity App { get; } |
|
||||
|
|
||||
public AppFeature(IAppEntity app) |
|
||||
{ |
|
||||
App = app; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,45 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// AppTrackingMiddleware.cs
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex Group
|
|
||||
// All rights reserved.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System.Diagnostics; |
|
||||
using System.Threading.Tasks; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using Squidex.Infrastructure.UsageTracking; |
|
||||
|
|
||||
namespace Squidex.Pipeline |
|
||||
{ |
|
||||
public sealed class AppTrackingMiddleware |
|
||||
{ |
|
||||
private readonly RequestDelegate next; |
|
||||
private readonly IUsageTracker usageTracker; |
|
||||
|
|
||||
public AppTrackingMiddleware(RequestDelegate next, IUsageTracker usageTracker) |
|
||||
{ |
|
||||
this.next = next; |
|
||||
this.usageTracker = usageTracker; |
|
||||
} |
|
||||
|
|
||||
public async Task Invoke(HttpContext context) |
|
||||
{ |
|
||||
var stopWatch = Stopwatch.StartNew(); |
|
||||
|
|
||||
await next(context); |
|
||||
|
|
||||
var appFeature = context.Features.Get<IAppFeature>(); |
|
||||
|
|
||||
if (appFeature?.App != null) |
|
||||
{ |
|
||||
stopWatch.Stop(); |
|
||||
|
|
||||
var weight = context.Features.Get<IAppTrackingWeightFeature>()?.Weight ?? 1; |
|
||||
|
|
||||
await usageTracker.TrackAsync(appFeature.App.Id.ToString(), weight, stopWatch.ElapsedMilliseconds); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,15 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// IAppTrackingWeightFeature.cs
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex Group
|
|
||||
// All rights reserved.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
namespace Squidex.Pipeline |
|
||||
{ |
|
||||
public interface IAppTrackingWeightFeature |
|
||||
{ |
|
||||
double Weight { get; } |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue