public void BannedClient_AfterExceeded_CanRequest() { //Arrange throttleOptionConfigurationMock.Setup(x => x.Value) .Returns(new ThrottleConfiguration { MaxRequests = 5, PenaltyTime = TimeSpan.FromSeconds(5), Period = TimeSpan.FromSeconds(1), ErrorMessage = "Too many requests." }); var memoryOptionsMock = new Mock <IOptions <MemoryCacheOptions> >(); memoryOptionsMock.Setup(x => x.Value) .Returns(new MemoryCacheOptions()); var throttleService = new ThrottleService(new MemoryCache(memoryOptionsMock.Object), throttleOptionConfigurationMock.Object, Mock.Of <ILogger <ThrottleService> >()); //Act var ip = faker.Internet.Ip(); for (int i = 0; i < 10; i++) { throttleService.IsAllowed(ip); } System.Threading.Thread.Sleep(TimeSpan.FromSeconds(6)); //Assert Assert.True(throttleService.IsAllowed(ip)); }
static void Main(string[] args) { ThrottleService throttleService = new ThrottleService(); List <QueueItem> testList = new List <QueueItem>(); TestAddItems(testList, "111", 10, QueueItemTypes.Comment); TestAddItems(testList, "333", 5, QueueItemTypes.Idea); TestAddItems(testList, "222", 6, QueueItemTypes.Comment); TestAddItems(testList, "111", 6, QueueItemTypes.Comment); foreach (QueueItem queueItem in testList) { throttleService.AddItem(queueItem); } //Tasks CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); while (!cancellationTokenSource.IsCancellationRequested) { Task.Factory.StartNew(ThrottlerManager.CheckThrottlers, cancellationTokenSource.Token); Thread.Sleep(1000); } }
/// <summary> /// Скачать страницу. /// </summary> /// <param name="chapterFolder">Папка для файлов.</param> public async Task Download(string chapterFolder) { this.IsDownloaded = false; if (restartCounter > MaxAttempt) { throw new DownloadAttemptFailed(restartCounter, this); } try { await DownloadManager.CheckPause().ConfigureAwait(false); using (await ThrottleService.WaitAsync().ConfigureAwait(false)) { await DownloadManager.CheckPause().ConfigureAwait(false); if (!DirectoryHelpers.ValidateSettingPath(chapterFolder)) { throw new DirectoryNotFoundException($"Попытка скачивания в папку {chapterFolder}, папка не существует."); } if (!Directory.Exists(chapterFolder)) { Directory.CreateDirectory(chapterFolder); } var manga = Chapter?.Volume?.Manga ?? Chapter?.Manga ?? Manga; var plugin = ConfigStorage.Plugins.Single(p => p.MangaType == manga.GetType()); var cache = MangaSettingCache.Get(plugin.GetType()); var file = await DownloadManager.DownloadImage(this.ImageLink, cache).ConfigureAwait(false); if (!file.Exist) { OnDownloadFailed(); } var fileName = this.Number.ToString(CultureInfo.InvariantCulture).PadLeft(4, '0') + "." + file.Extension; await file.Save(Path.Combine(chapterFolder, fileName)).ConfigureAwait(false); this.IsDownloaded = true; } } catch (System.Exception ex) { Log.Exception(ex, this.Uri.OriginalString); ++restartCounter; await Download(chapterFolder).ConfigureAwait(false); } }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", "options", Route = null)] HttpRequest req, [StorageAccount("StorageConnectionString")] CloudStorageAccount storageAccount, TraceWriter log ) { var email = req.Query["email"].FirstOrDefault()?.ToLower(); if (string.IsNullOrWhiteSpace(email)) { return(new BadRequestObjectResult("The query parameter \"email\" is empty or missing")); } log.Info($"E-mail verification request received for {email}"); var client = storageAccount.CreateCloudTableClient(); var throttleService = new ThrottleService(client, log); var throttled = (await throttleService.ThrottleOrIncrement(email)) || (await throttleService.ThrottleOrIncrement(IpUtility.GetClientIp(req))); if (throttled) { return(new StatusCodeResult(429)); } var code = $"{new Random().Next(100, 999)}{new Random().Next(100, 999)}{new Random().Next(100, 999)}"; var token = Guid.NewGuid().ToString().Replace("-", ""); var auth = new EmailAuthToken(email, token, code) { Expiration = DateTimeOffset.UtcNow.AddHours(4), }; var secret = Environment.GetEnvironmentVariable("email-secret", EnvironmentVariableTarget.Process); if (Upload(log, "http://grimdawn.dreamcrash.org/ia/backup/auth.php", $"token={secret}&target={email}&code={code}")) { var table = client.GetTableReference(EmailAuthToken.TableName); await table.CreateIfNotExistsAsync(); await table.ExecuteAsync(TableOperation.Insert(auth)); log.Info($"Successfully posted email for {email}"); } return(new OkObjectResult(new ResponseDto { Token = token })); }
private static async Task <(HttpResponseMessage, System.Exception)> DoWithRestarts(Uri uri, HttpClient client, Func <Uri, HttpClient, Task <HttpResponseMessage> > func, int restartCounter = 0) { try { if (restartCounter > 3) { throw new DownloadAttemptFailed(restartCounter, uri); } HttpResponseMessage content; using (await ThrottleService.WaitAsync().ConfigureAwait(false)) { content = await func(uri, client).ConfigureAwait(false); } if (await RequestCanBeRetry(content).ConfigureAwait(false)) { Log.Error($"{Strings.Page_GetPage_SiteOff}, код {content.StatusCode}, ссылка: {uri}, попытка номер - {restartCounter}"); ++restartCounter; return(await DoWithRestarts(uri, client, func, restartCounter).ConfigureAwait(false)); } return(content, null); } catch (TaskCanceledException ex) { Log.Exception(ex, $"{Strings.Page_GetPage_SiteOff}, ссылка: {uri}, попытка номер - {restartCounter}"); ++restartCounter; return(await DoWithRestarts(uri, client, func, restartCounter).ConfigureAwait(false)); } catch (HttpRequestException ex) when(ex.InnerException is System.Net.Sockets.SocketException || ex.InnerException is System.IO.IOException) { Log.Exception(ex, $"{Strings.Page_GetPage_SiteOff}, ссылка: {uri}, попытка номер - {restartCounter}"); ++restartCounter; return(await DoWithRestarts(uri, client, func, restartCounter).ConfigureAwait(false)); } catch (System.Exception ex) { Log.Exception(ex, $"Не удалось получить страницу: {uri}"); return(null, ex); } }
/// <summary> /// Скачать страницу. /// </summary> /// <param name="chapterFolder">Папка для файлов.</param> public async Task Download(string chapterFolder) { this.IsDownloaded = false; if (restartCounter > MaxAttempt) { throw new DownloadAttemptFailed(restartCounter, this); } try { await DownloadManager.CheckPause(); using (await ThrottleService.WaitAsync()) { await DownloadManager.CheckPause(); chapterFolder = DirectoryHelpers.MakeValidPath(chapterFolder); if (!Directory.Exists(chapterFolder)) { Directory.CreateDirectory(chapterFolder); } var file = await DownloadManager.DownloadImage(this.ImageLink); if (!file.Exist) { OnDownloadFailed(); } var fileName = this.Number.ToString(CultureInfo.InvariantCulture).PadLeft(4, '0') + "." + file.Extension; await file.Save(Path.Combine(chapterFolder, fileName)); this.IsDownloaded = true; } } catch (System.Exception ex) { Log.Exception(ex, this.Uri.OriginalString); ++restartCounter; await Download(chapterFolder); } }
/// <summary> /// Initializes a new instance of the <see cref="ThrottleActionFilter"/> class. /// </summary> public ThrottleActionFilter(ThrottleService throttleService, SiteConfig siteConfig, ILicenseManager licenseManager) { this.siteConfig = siteConfig; this.throttleService = throttleService; this.licenseManager = licenseManager; }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", "options", Route = null)] HttpRequest req, [StorageAccount("StorageConnectionString")] CloudStorageAccount storageAccount, TraceWriter log ) { var token = req.Query["token"]; var code = req.Query["code"]; var client = storageAccount.CreateCloudTableClient(); if (string.IsNullOrWhiteSpace(token)) { return(new BadRequestObjectResult("The query parameter \"token\" is empty or missing")); } else if (string.IsNullOrWhiteSpace(code)) { return(new BadRequestObjectResult("The query parameter \"code\" is empty or missing")); } log.Info($"E-mail verification request received for {token}"); // Throttling required for verification as well, to prevent infinite attempts on a token. var throttleService = new ThrottleService(storageAccount.CreateCloudTableClient(), log); var throttled = (await throttleService.ThrottleOrIncrement("attempt-" + token)) || (await throttleService.ThrottleOrIncrement("attempt-" + IpUtility.GetClientIp(req))); if (throttled) { return(new StatusCodeResult(429)); } var table = client.GetTableReference(EmailAuthToken.TableName); await table.CreateIfNotExistsAsync(); var query = TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, token), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, code) ); var exQuery = new TableQuery <EmailAuthToken>().Where(query); var entry = await QueryHelper.Get(table, exQuery); if (entry != null) { if (DateTimeOffset.UtcNow < entry.Expiration) { log.Info($"Authentication successful for {entry.Email}"); var auth = new Authentication { PartitionKey = Authentication.PartitionName, RowKey = (Guid.NewGuid().ToString() + Guid.NewGuid().ToString()).Replace("-", ""), Identity = entry.Email }; var authTable = client.GetTableReference(Authentication.TableName); await authTable.CreateIfNotExistsAsync(); await authTable.ExecuteAsync(TableOperation.Insert(auth)); return(new OkObjectResult(new VerifyEmailTokenResponseDto { Success = true, Token = auth.RowKey })); } else { log.Info($"Authentication token {token} for {entry.Email} has already expired, expiration {entry.Expiration}"); return(new OkObjectResult(new VerifyEmailTokenResponseDto { Success = false })); } } else { log.Info("No entry found"); return(new OkObjectResult(new VerifyEmailTokenResponseDto { Success = false })); } }