public SterlingCacheContentTest() { primaryKey = new PrimaryCacheKey("https://localhost/test", "POST"); secondaryKey = TestHelper.CreateContentKey(); entry = new CacheEntry(primaryKey, new string[0]); response = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent("42") }; response.Headers.CacheControl = new CacheControlHeaderValue() { MaxAge = TimeSpan.FromHours(1) }; response.Content.Headers.ContentLanguage.Add("de"); // We need to add this here, since the header will be added during reconstruction in any case // That is (hopefully) not a problem, however, since it does not contribute to the "content" as such. response.Content.Headers.ContentLength = 2; content = new CacheContent() { PrimaryKey = primaryKey, ContentKey = secondaryKey, Response = response }; }
public async Task UpdateEntryAsync(CacheContent content) { CacheEntry entry = content.CacheEntry; InMemmoryCacheEntry inMemoryCacheEntry = null; if (!_responseCache.ContainsKey(entry.Key)) { inMemoryCacheEntry = new InMemmoryCacheEntry(entry); lock (syncRoot) { _responseCache[entry.Key] = inMemoryCacheEntry; } } else { inMemoryCacheEntry = _responseCache[entry.Key]; } var newContent = await CloneAsync(content); lock (syncRoot) { inMemoryCacheEntry.Responses[content.Key] = newContent; } }
public void Creation_fails_for_invalid_CacheContent() { // Arrange var primaryKey = new PrimaryCacheKey("https://localhost/test", "POST"); var secondaryKey = TestHelper.CreateContentKey(); var entry = new CacheEntry(primaryKey, new string[0]); var response = new HttpResponseMessage(); var noPrimary = new CacheContent() { ContentKey = secondaryKey, Response = response }; var noContentKey = new CacheContent() { Response = response }; var noResponse = new CacheContent() { PrimaryKey = primaryKey, ContentKey = secondaryKey, }; // Act // Assert Assert.Throws <ArgumentException>(() => SterlingCacheContent.CreateAsync(noPrimary).Result); Assert.Throws <ArgumentException>(() => SterlingCacheContent.CreateAsync(noContentKey).Result); Assert.Throws <ArgumentException>(() => SterlingCacheContent.CreateAsync(noResponse).Result); }
public static CacheQueryResult Revalidate(CacheContent cacheContent) { return(new CacheQueryResult() { Status = CacheStatus.Revalidate, SelectedVariant = cacheContent }); }
public static CacheQueryResult ReturnStored(CacheContent cacheContent) { return(new CacheQueryResult() { Status = CacheStatus.ReturnStored, SelectedVariant = cacheContent }); }
private async Task<CacheContent> CloneAsync(CacheContent cacheContent) { var newResponse = await new HttpMessageContent(cacheContent.Response).ReadAsHttpResponseMessageAsync(); var newContent = new CacheContent() { CacheEntry = cacheContent.CacheEntry, Key = cacheContent.Key, Expires = cacheContent.Expires, HasValidator = cacheContent.HasValidator, CacheControl = cacheContent.CacheControl, Response = newResponse }; return newContent; }
public async Task Creation_does_not_fail_with_empty_message() { // Arrange var primaryKey = new PrimaryCacheKey("https://localhost/test", "POST"); var secondaryKey = TestHelper.CreateContentKey(); var entry = new CacheEntry(primaryKey, new string[0]); var response = new HttpResponseMessage(); var content = new CacheContent() { PrimaryKey = primaryKey, ContentKey = secondaryKey, Response = response }; // Act var sterlingContent = await SterlingCacheContent.CreateAsync(content); // Assert Assert.NotNull(sterlingContent); }
public async Task Creation_does_not_fail_with_empty_message() { // Arrange var primaryKey = new PrimaryCacheKey("https://localhost/test", "POST"); var secondaryKey = TestHelper.CreateContentKey(); var entry = new CacheEntry(primaryKey, new string[0]); var response = new HttpResponseMessage(); var content = new CacheContent() { PrimaryKey = primaryKey, ContentKey = secondaryKey, Response = response }; // Act var sterlingContent = await SterlingCacheContent.CreateAsync(content); // Assert Assert.NotNull(sterlingContent); }
public static async Task <SterlingCacheContent> CreateAsync(CacheContent content) { Contract.Requires <ArgumentException>(content.PrimaryKey != null, "content"); Contract.Requires <ArgumentException>(content.ContentKey != null, "content"); Contract.Requires <ArgumentException>(content.Response != null, "content"); var sterlingContent = new SterlingCacheContent(); //if (content.CacheEntry is SterlingCacheEntry) //{ // sterlingContent.CacheEntry = content.CacheEntry as SterlingCacheEntry; //} //else //{ // sterlingContent.CacheEntry = new SterlingCacheEntry(content.CacheEntry); //} //sterlingContent.Key = content.Key; //var response = content.Response; //sterlingContent.StatusCode = response.StatusCode; //foreach (var keyValue in response.Headers) //{ // sterlingContent.ResponseHeaders.Add(keyValue.Key, keyValue.Value); //} //if (response.Content != null) //{ // foreach (var keyValue in response.Content.Headers) // { // sterlingContent.ContentHeaders.Add(keyValue.Key, keyValue.Value); // } // sterlingContent.Content = await response.Content.ReadAsByteArrayAsync(); //} return(sterlingContent); }
public static async Task<SterlingCacheContent> CreateAsync(CacheContent content) { Contract.Requires<ArgumentException>(content.PrimaryKey != null, "content"); Contract.Requires<ArgumentException>(content.ContentKey != null, "content"); Contract.Requires<ArgumentException>(content.Response != null, "content"); var sterlingContent = new SterlingCacheContent(); //if (content.CacheEntry is SterlingCacheEntry) //{ // sterlingContent.CacheEntry = content.CacheEntry as SterlingCacheEntry; //} //else //{ // sterlingContent.CacheEntry = new SterlingCacheEntry(content.CacheEntry); //} //sterlingContent.Key = content.Key; //var response = content.Response; //sterlingContent.StatusCode = response.StatusCode; //foreach (var keyValue in response.Headers) //{ // sterlingContent.ResponseHeaders.Add(keyValue.Key, keyValue.Value); //} //if (response.Content != null) //{ // foreach (var keyValue in response.Content.Headers) // { // sterlingContent.ContentHeaders.Add(keyValue.Key, keyValue.Value); // } // sterlingContent.Content = await response.Content.ReadAsByteArrayAsync(); //} return sterlingContent; }
public void LoadTexture(string path_, Action <Texture> cb_) { Texture tex = null; if (_cache.ContainsKey(path_)) { _cache[path_].count += 1; cb_(_cache[path_].tex); return; } tex = Resources.Load(path_) as Texture; if (null == tex) { tex = _defaultTex; } var content = new CacheContent(); content.count = 0; content.path = path_; content.tex = tex; _cache[path_] = content; cb_(tex); }
public SterlingCacheContentTest() { primaryKey = new PrimaryCacheKey("https://localhost/test", "POST"); secondaryKey = TestHelper.CreateContentKey(); entry = new CacheEntry(primaryKey, new string[0]); response = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent("42") }; response.Headers.CacheControl = new CacheControlHeaderValue() { MaxAge = TimeSpan.FromHours(1) }; response.Content.Headers.ContentLanguage.Add("de"); // We need to add this here, since the header will be added during reconstruction in any case // That is (hopefully) not a problem, however, since it does not contribute to the "content" as such. response.Content.Headers.ContentLength = 2; content = new CacheContent() { PrimaryKey = primaryKey, ContentKey = secondaryKey, Response = response }; }
public void Add(CacheContent item) { _content.Add(item); }
public Task UpdateEntryAsync(CacheContent content) { throw new NotImplementedException(); }
private async Task Cache(HttpContext context) { //bool useMinification = _options.EnableMinification && _minificationManagers.Count > 0; //bool useCompression = _options.EnableCompression && _compressionManager != null; var useMinification = _options.EnableMinification; var useCompression = _options.EnableCompression; var cacheSetting = _options.Setting; var currentUrl = context.Request.Path.Value; var accept = $"{context.Request.Headers["Accept"]}"; var isHtml = context.Request.Method == "GET" && !string.IsNullOrEmpty(accept) && accept.Contains("text/html") && context.Request.Headers["X-Requested-With"] != "XMLHttpRequest"; #region 做缓存处理 if (!isHtml || (!useMinification && !useCompression) || !_options.EnableCache || !cacheSetting.IgnorePages.Contains(currentUrl)) { await _next.Invoke(context); return; } #endregion var cachePage = cacheSetting.CachePages.FirstOrDefault(a => a.Url == currentUrl); if (cachePage == null) { cachePage = new CachePage() { Url = currentUrl } } ; if (cachePage.CacheTime == 0) { cachePage.CacheTime = cacheSetting.CacheTime; } var cacheKey = GetKey(context.Request, cachePage.VaryByParams); #region 判断缓存是否存在 var cacheContent = _cacheService.Get <CacheContent>(cacheKey); if (cacheContent != null) { context.Response.Headers.Add("C-Cache", "Hit"); if (cacheContent.Headers != null && cacheContent.Headers.Count > 0) { foreach (var ch in cacheContent.Headers) { context.Response.Headers.Add(ch.Key, ch.Value); } } await context.Response.Body.WriteAsync(cacheContent.Content, 0, cacheContent.Content.Length); return; } #endregion HttpRequest request = context.Request; HttpResponse response = context.Response; using (var cachedStream = new MemoryStream()) { Stream originalStream = response.Body; response.Body = cachedStream; try { await _next.Invoke(context); } catch (Exception) { response.Body = originalStream; cachedStream.Clear(); throw; } byte[] cachedBytes = cachedStream.ToArray(); int cachedByteCount = cachedBytes.Length; bool isProcessed = false; response.Body = originalStream; cachedStream.Clear(); if (cachedByteCount == 0) { return; } if (response.StatusCode == 200) { string httpMethod = request.Method; string contentType = response.ContentType; string mediaType = null; Encoding encoding = null; if (contentType != null) { MediaTypeHeaderValue mediaTypeHeader; if (MediaTypeHeaderValue.TryParse(contentType, out mediaTypeHeader)) { mediaType = mediaTypeHeader.MediaType.Value; encoding = mediaTypeHeader.Encoding; } } encoding = encoding ?? Encoding.GetEncoding(0); string content = encoding.GetString(cachedBytes); string processedContent = content; IHeaderDictionary responseHeaders = response.Headers; bool isEncodedContent = responseHeaders.IsEncodedContent(); Action <string, string> appendHttpHeader = (key, value) => { responseHeaders.Append(key, new StringValues(value)); }; #region Html压缩 if (useMinification && _options.IsAllowableResponseSize(cachedByteCount)) { var htmlMinifier = new HtmlMinifier(); var result = htmlMinifier.Minify(processedContent); if (result.Errors.Count == 0) { processedContent = result.MinifiedContent; isProcessed = true; } //foreach (IMarkupMinificationManager minificationManager in _minificationManagers) //{ // if (minificationManager.IsSupportedHttpMethod(httpMethod) // && mediaType != null && minificationManager.IsSupportedMediaType(mediaType) // && minificationManager.IsProcessablePage(currentUrl)) // { // if (isEncodedContent) // { // throw new InvalidOperationException( // string.Format( // AspNetCommonStrings.MarkupMinificationIsNotApplicableToEncodedContent, // responseHeaders["Content-Encoding"] // ) // ); // } // IMarkupMinifier minifier = minificationManager.CreateMinifier(); // MarkupMinificationResult minificationResult = minifier.Minify(processedContent, // currentUrl, encoding, minificationManager.GenerateStatistics); // if (minificationResult.Errors.Count == 0) // { // processedContent = minificationResult.MinifiedContent; // isProcessed = true; // } // } // if (isProcessed) // { // break; // } //} } #endregion byte[] processedBytes; if (isProcessed) { processedBytes = encoding.GetBytes(processedContent); } else { processedBytes = cachedBytes; } #region GZip压缩 if (useCompression && !isEncodedContent) { string acceptEncoding = request.Headers["Accept-Encoding"]; string[] encodingTokens = acceptEncoding .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(e => e.Trim().ToLowerInvariant()) .ToArray(); ICompressor compressor = null; foreach (var et in encodingTokens) { if (et == EncodingTokenConstants.Deflate) { compressor = new DeflateCompressor(new DeflateCompressionSettings() { Level = System.IO.Compression.CompressionLevel.Fastest }); break; } else if (et == EncodingTokenConstants.GZip) { compressor = new GZipCompressor(new GZipCompressionSettings() { Level = System.IO.Compression.CompressionLevel.Fastest }); } } if (compressor != null) { using (var inputStream = new MemoryStream(processedBytes)) using (var outputStream = new MemoryStream()) { using (Stream compressedStream = compressor.Compress(outputStream)) { await inputStream.CopyToAsync(compressedStream); } byte[] compressedBytes = outputStream.ToArray(); processedBytes = compressedBytes; outputStream.Clear(); inputStream.Clear(); responseHeaders["Content-Length"] = compressedBytes.Length.ToString(); compressor.AppendHttpHeaders(appendHttpHeader); await originalStream.WriteAsync(compressedBytes, 0, compressedBytes.Length); } } //using (var inputStream = new MemoryStream(processedBytes)) //using (var outputStream = new MemoryStream()) //{ // string acceptEncoding = request.Headers["Accept-Encoding"]; // ICompressor compressor = _compressionManager.CreateCompressor(acceptEncoding); // using (Stream compressedStream = compressor.Compress(outputStream)) // { // await inputStream.CopyToAsync(compressedStream); // } // byte[] compressedBytes = outputStream.ToArray(); // processedBytes = compressedBytes; // int compressedByteCount = compressedBytes.Length; // outputStream.Clear(); // inputStream.Clear(); // responseHeaders["Content-Length"] = compressedByteCount.ToString(); // compressor.AppendHttpHeaders(appendHttpHeader); // await originalStream.WriteAsync(compressedBytes, 0, compressedByteCount); //} isProcessed = true; } #endregion else { if (isProcessed) { int processedByteCount = processedBytes.Length; responseHeaders["Content-Length"] = processedByteCount.ToString(); await originalStream.WriteAsync(processedBytes, 0, processedByteCount); } } #region 保存到缓存中 cacheContent = new CacheContent() { Content = processedBytes, ContentType = contentType, Headers = new Dictionary <string, string>() }; foreach (var rh in responseHeaders) { cacheContent.Headers.Add(rh.Key, rh.Value); } await _cacheService.SetAsync(cacheKey, cacheContent, TimeSpan.FromSeconds(cachePage.CacheTime)); context.Response.Headers.Add("C-Cache", "Cached"); //Task.Factory.StartNew(obj => //{ // var cc = (CacheContent)obj; //}, cacheContent); #endregion } if (!isProcessed) { await originalStream.WriteAsync(cachedBytes, 0, cachedByteCount); } } }
public void Creation_fails_for_invalid_CacheContent() { // Arrange var primaryKey = new PrimaryCacheKey("https://localhost/test", "POST"); var secondaryKey = TestHelper.CreateContentKey(); var entry = new CacheEntry(primaryKey, new string[0]); var response = new HttpResponseMessage(); var noPrimary = new CacheContent() { ContentKey = secondaryKey, Response = response }; var noContentKey = new CacheContent() { Response = response }; var noResponse = new CacheContent() { PrimaryKey = primaryKey, ContentKey = secondaryKey, }; // Act // Assert Assert.Throws<ArgumentException>(() => SterlingCacheContent.CreateAsync(noPrimary).Result); Assert.Throws<ArgumentException>(() => SterlingCacheContent.CreateAsync(noContentKey).Result); Assert.Throws<ArgumentException>(() => SterlingCacheContent.CreateAsync(noResponse).Result); }
public void Add(CacheContent content) { _contents.Add(content); }
public void PersistAdd(CacheContent content) { PersistContents.Add(content); SavePersistContents(); }