public void SetAndExists() { string key = "6"; var result = _redisDatabase.Set(key, "呼吁", TimeSpan.FromSeconds(60)); //var result = RedisHelper.Set(key, "呼吁", TimeSpan.FromSeconds(60)); var isExists = _redisDatabase.Exists(key); Assert.AreEqual(true, result); }
public string TestRedis(string key) { if (!string.IsNullOrWhiteSpace(key)) { if (redisManager_.IsExits(key)) { string value = redisManager_.GetTEntity <string>(key); return(value); } else { redisManager_.Set(key, "set_" + key, TimeSpan.FromSeconds(90)); return("push " + key); } } else { return("key is null"); } }
public IActionResult SetDashData([FromBody] RequestDashData request) { var model = _redisManager.Get <RequestDashData>(RedisConstant.DashData); if (model == null) { model = request; } else { //Mapper Function foreach (var prop in model.GetType().GetProperties()) { prop.SetValue(model, (int)prop.GetValue(request) + (int)prop.GetValue(model)); } } _redisManager.Set(RedisConstant.DashData, model, TimeSpan.FromDays(1)); _hubContext.Clients.All.SendAsync("GetDashData", SerializeHelper.Serialize(model)); return(new ObjectResult(model)); }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="next"></param> /// <returns></returns> public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { IServiceProvider serviceProvider = context.HttpContext.RequestServices; var responseCacheOption = serviceProvider.GetService <ResponseCacheOption>(); //配置存在且配置关闭或者持续时长等于0,即忽略响应缓存 if ((responseCacheOption != null && !responseCacheOption.Enabled) || Duration == 0) { goto gotoNext; } context.HttpContext.Request.EnableBuffering(); var _logger = serviceProvider.GetRequiredService <ILogger <PostResponseCacheAttribute> >(); var _configuration = serviceProvider.GetRequiredService <IConfiguration>(); var _memorycache = serviceProvider.GetService <IMemoryCache>(); IRedisManager _redisManager = null; if ((responseCacheOption != null && responseCacheOption.Cluster) || Cluster) { _redisManager = serviceProvider.GetService <IRedisManager>(); if (_redisManager == null) { throw new ArgumentNullException(nameof(IMemoryCache), "Post响应已启用集群模式,缓存依赖IRedisManager,请services.AddRedisManager()注入IRedisManager后再使用[PostResponseCache]"); } } if (_memorycache == null) { throw new ArgumentNullException(nameof(IMemoryCache), "Post响应缓存依赖IMemoryCache,请services.AddMemoryCache()注入IMemoryCache后再使用[PostResponseCache]"); } //标识已触发过响应缓存,防止中间件再次触发 _memorycache.Set($"PostResponseCache_{context.HttpContext.Request.Path}", "标识已触发过响应缓存,防止中间件再次触发", new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5) }); var _requestCacheData = serviceProvider.GetService <RequestCacheData>(); if (_requestCacheData == null) { throw new ArgumentNullException(nameof(IMemoryCache), "Post响应缓存依赖ResponseCacheData,请调用services.AddShareRequestBody()注入后再使用[PostResponseCache]"); } var token = context.HttpContext.RequestAborted.Register(async() => { await Task.CompletedTask; return; }); var descriptor = (Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor; var attribute = (IgnorePostResponseCacheAttribute)descriptor.MethodInfo.GetCustomAttributes(typeof(IgnorePostResponseCacheAttribute), true).FirstOrDefault(); if (attribute != null) { //记录忽略的路由,中间件跳过 _memorycache.Set($"IgnorePostResponseCache_{context.HttpContext.Request.Path}", true, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5) }); goto gotoNext; } if (context.HttpContext.Request.Method.Equals("get", StringComparison.OrdinalIgnoreCase) || context.HttpContext.Request.Method.Equals("head", StringComparison.OrdinalIgnoreCase)) { goto gotoNext; } else { var convertedDictionatry = context.HttpContext.Request.Query.ToDictionary(s => s.Key.ToLower(), s => s.Value); if (IgnoreVaryByQueryKeys == null || !IgnoreVaryByQueryKeys.Any()) { if (responseCacheOption.IgnoreVaryByQueryKeys.Any()) { IgnoreVaryByQueryKeys = responseCacheOption.IgnoreVaryByQueryKeys.ToArray(); } } foreach (var item in IgnoreVaryByQueryKeys ?? new string[0]) { if (convertedDictionatry.ContainsKey(item.ToLower())) { convertedDictionatry.Remove(item.ToLower()); } } StringBuilder requestStrKey = new StringBuilder(context.HttpContext.Request.Path); foreach (var item in convertedDictionatry) { requestStrKey.Append($"{item.Key}{item.Value}"); } string bodyValue; if (_requestCacheData == null || string.IsNullOrEmpty(_requestCacheData.Body)) { bodyValue = await Common.ReadAsString(context.HttpContext); _requestCacheData = new RequestCacheData { Body = bodyValue }; } else { bodyValue = _requestCacheData.Body; } if (!string.IsNullOrEmpty(bodyValue) && !"null".Equals(bodyValue)) { //非Get请求body有值才被缓存,其他默认不缓存,防止body读取失败导致缓存异常 bodyValue = Regex.Replace(bodyValue, @"\s(?=([^""]*""[^""]*"")*[^""]*$)", string.Empty); bodyValue = bodyValue.Replace("\r\n", "").Replace(" : ", ":").Replace("\n ", "").Replace("\n", "").Replace(": ", ":").Replace(", ", ","); requestStrKey.Append($"body{bodyValue}"); ResponseCacheData cacheResponseBody = null; if (Cluster) { cacheResponseBody = _redisManager.Get <ResponseCacheData>($"NetProPostResponse:{requestStrKey}"); } else { cacheResponseBody = _memorycache.Get <ResponseCacheData>($"NetProPostResponse:{requestStrKey}"); } if (cacheResponseBody != null && !context.HttpContext.RequestAborted.IsCancellationRequested) { if (!context.HttpContext.Response.HasStarted) { _logger.LogInformation($"触发PostResponseCacheAttribute本地缓存"); switch (ResponseMode) { case ResponseMode.Cache: context.HttpContext.Response.StatusCode = cacheResponseBody.StatusCode; context.HttpContext.Response.ContentType = cacheResponseBody.ContentType; await context.HttpContext.Response.WriteAsync(cacheResponseBody.Body); await Task.CompletedTask; return; case ResponseMode.Error: if (cacheResponseBody.StatusCode == 200) { //TODO确定StatusCode与Headers响应的先后顺序 context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict; context.HttpContext.Response.Headers.Add("Kestrel-ResponseMode", $"{ResponseMode}"); context.HttpContext.Response.ContentType = cacheResponseBody.ContentType; await context.HttpContext.Response.WriteAsync(JsonSerializer.Serialize(new { Code = -1, Msg = $"{Message}" }, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All) }), Encoding.UTF8); await Task.CompletedTask; return; } else { context.HttpContext.Response.StatusCode = cacheResponseBody.StatusCode; context.HttpContext.Response.ContentType = cacheResponseBody.ContentType; await context.HttpContext.Response.WriteAsync(cacheResponseBody.Body); await Task.CompletedTask; return;; } } } else { _logger.LogError($"StatusCode无法设置,因为响应已经启动,位置为:触发本地缓存开始赋值[responsecache2]"); await Task.CompletedTask; return; } } else if (!context.HttpContext.RequestAborted.IsCancellationRequested) { try { var actionResult = await next(); dynamic responseResult = (dynamic)actionResult.Result; if (actionResult.Exception != null) { // 过滤器中await next();执行的始终是Action而不是下一个过滤器或者中间件 await Task.CompletedTask; return; } if (responseResult == null) { await Task.CompletedTask; return; } if (responseResult.GetType().Name == "EmptyResult") { await Task.CompletedTask; return; } string body = string.Empty; if (responseResult as Microsoft.AspNetCore.Mvc.ObjectResult != null) { body = JsonSerializer.Serialize(responseResult.Value, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All) }); } if (Cluster) { _redisManager.Set($"NetProPostResponse:{requestStrKey}", new ResponseCacheData { Body = body, ContentType = "application/json", StatusCode = responseResult.StatusCode ?? 200, }, TimeSpan.FromSeconds(Duration)); } else { _memorycache.Set($"NetProPostResponse:{requestStrKey}", new ResponseCacheData { Body = body, ContentType = "application/json", StatusCode = responseResult.StatusCode ?? 200, }, TimeSpan.FromSeconds(Duration)); } } catch (Exception ex) { await Task.CompletedTask; return; } await Task.CompletedTask; return; } else if (context.HttpContext.RequestAborted.IsCancellationRequested) { await Task.CompletedTask; return; } } else if (!context.HttpContext.RequestAborted.IsCancellationRequested) { goto gotoNext; } else { await Task.CompletedTask; return; } } gotoNext: await next(); }
public void Set(string key, RateLimitCounter counter, TimeSpan expiration) { _manager.Set(key, counter, expiration); }
/// <summary> /// Post:(从头排序后+body json整体 )hash /// </summary> /// <param name="context"></param> /// <param name="responseCacheData">自定义对象不能ctor注入</param> /// <returns></returns> public async Task InvokeAsync(HttpContext context, ResponseCacheData responseCacheData, RequestCacheData requestCacheData) { context.Request.EnableBuffering(); var token = context.RequestAborted.Register(async() => { await Task.CompletedTask; return; }); var endpoint = context.GetEndpoint(); if (endpoint != null) { if (endpoint.Metadata .Any(m => m is IgnorePostResponseCacheAttribute)) { goto gotoNext; } } if (context.Request.Method.Equals("get", StringComparison.OrdinalIgnoreCase) || context.Request.Method.Equals("head", StringComparison.OrdinalIgnoreCase) || _memorycache.TryGetValue($"PostResponseCache_{context.Request.Path}", out object _tempIgnoe) || _memorycache.TryGetValue($"IgnorePostResponseCache_{context.Request.Path}", out object _temp)) { goto gotoNext; } else { var convertedDictionatry = context.Request.Query.ToDictionary(s => s.Key.ToLower(), s => s.Value); foreach (var item in _responseCacheOption?.IgnoreVaryByQueryKeys ?? new List <string>()) { if (convertedDictionatry.ContainsKey(item.ToLower())) { convertedDictionatry.Remove(item.ToLower()); } } StringBuilder requestStrKey = new StringBuilder(context.Request.Path); foreach (var item in convertedDictionatry) { requestStrKey.Append($"{item.Key}{item.Value}"); } string bodyValue; if (requestCacheData == null || string.IsNullOrEmpty(requestCacheData.Body)) { bodyValue = await Common.ReadAsString(context); requestCacheData = new RequestCacheData { Body = bodyValue }; } else { bodyValue = requestCacheData.Body; } if (!string.IsNullOrEmpty(bodyValue) && !"null".Equals(bodyValue)) { //非Get请求body有值才被缓存,其他默认不缓存,防止body读取失败导致缓存异常 bodyValue = Regex.Replace(bodyValue, @"\s(?=([^""]*""[^""]*"")*[^""]*$)", string.Empty); bodyValue = bodyValue.Replace("\r\n", "").Replace(" : ", ":").Replace("\n ", "").Replace("\n", "").Replace(": ", ":").Replace(", ", ","); requestStrKey.Append($"body{bodyValue}"); ResponseCacheData cacheResponseBody = null; IRedisManager _redisManager = null; if (_responseCacheOption.Cluster) { _redisManager = context.RequestServices.GetService <IRedisManager>(); if (_redisManager == null) { throw new ArgumentNullException(nameof(RedisCacheOption), $"PostResponseCache组件在集群模式下未检测到注入NetPro.CsRedis组件,请检查是否遗漏{nameof(RedisCacheOption)}配置节点"); } cacheResponseBody = _redisManager.Get <ResponseCacheData>($"NetProPostResponse:{requestStrKey}"); } else { cacheResponseBody = _memorycache.Get <ResponseCacheData>($"NetProPostResponse:{requestStrKey}"); } if (cacheResponseBody != null && !context.RequestAborted.IsCancellationRequested) { //https://stackoverflow.com/questions/45675102/asp-net-core-middleware-cannot-set-status-code-on-exception-because-response-ha if (!context.Response.HasStarted) { context.Response.StatusCode = cacheResponseBody.StatusCode; context.Response.ContentType = cacheResponseBody.ContentType; await context.Response.WriteAsync(cacheResponseBody.Body); _iLogger.LogInformation($"触发PostResponseCacheMiddleware本地缓存"); //直接return可避免此错误 :OnStarting cannot be set because the response has already started. await Task.CompletedTask; return; } else { _iLogger.LogError($"StatusCode无法设置,因为响应已经启动,位置为:触发本地缓存开始赋值[responsecache2]"); await Task.CompletedTask; return; } } else if (!context.RequestAborted.IsCancellationRequested) { Stream originalBody = context.Response.Body; try { using (var memStream = new MemoryStream()) { context.Response.Body = memStream; await _next(context); memStream.Position = 0; string responseBody = new StreamReader(memStream).ReadToEnd(); responseCacheData = new ResponseCacheData { Body = responseBody, ContentType = context.Response.ContentType, StatusCode = context.Response.StatusCode }; memStream.Position = 0; await memStream.CopyToAsync(originalBody); if (_responseCacheOption.Cluster) { _redisManager.Set($"NetProPostResponse:{requestStrKey}", new ResponseCacheData { Body = responseBody, ContentType = context.Response.ContentType, StatusCode = context.Response.StatusCode }, TimeSpan.FromSeconds(_responseCacheOption.Duration)); } else { _memorycache.Set <ResponseCacheData>($"NetProPostResponse:{requestStrKey}", new ResponseCacheData { Body = responseBody, ContentType = context.Response.ContentType, StatusCode = context.Response.StatusCode }, TimeSpan.FromSeconds(_responseCacheOption.Duration)); } } await Task.CompletedTask; return; } finally { context.Response.Body = originalBody; } } else if (context.RequestAborted.IsCancellationRequested) { await Task.CompletedTask; return; } } else if (!context.RequestAborted.IsCancellationRequested) { goto gotoNext; } else { await Task.CompletedTask; return; } } gotoNext: await _next(context); }