public void CacheHitTest() { if (Directory.Exists(Flickr.CacheLocation)) { Directory.Delete(Flickr.CacheLocation, true); } Flickr f = TestData.GetInstance(); Flickr.FlushCache(); f.InstanceCacheDisabled = false; f.PeopleGetPublicPhotos(TestData.TestUserId); string lastUrl = f.LastRequest; ICacheItem item = Cache.Responses.Get(lastUrl, TimeSpan.MaxValue, false); Assert.IsNotNull(item, "Cache should now contain the item."); Assert.IsInstanceOf <ResponseCacheItem>(item); ResponseCacheItem response = item as ResponseCacheItem; Assert.IsNotNull(response.Url, "Url should not be null."); Assert.AreEqual(lastUrl, response.Url.AbsoluteUri, "Url should match the url requested from the cache."); }
static void SaveResponseHeaders(HttpResponseMessage response, ResponseCacheItem itm) { foreach (var header in response.Headers) { if (!header.Key.Equals("Set-Cookie", StringComparison.OrdinalIgnoreCase) && !header.Key.Equals("cookie", StringComparison.OrdinalIgnoreCase)) { itm.Headers[header.Key] = header.Value.ToArray(); } } foreach (var header in response.Content.Headers) { itm.ContentHeaders[header.Key] = header.Value.ToArray(); } }
public static ResponseCacheItem ForStreamContent(HttpResponseMessage response, string storageKey) { var itm = new ResponseCacheItem { StorageKey = storageKey, Content = null, Status = (int)response.StatusCode, Headers = new Dictionary <string, string[]>(), ContentHeaders = new Dictionary <string, string[]>(), MediaType = response.Content.Headers.ContentType.MediaType, Url = response.RequestMessage.RequestUri.ToString(), Version = response.Version }; SaveResponseHeaders(response, itm); return(itm); }
/// <summary> /// writes the content to the file system cache /// </summary> /// <param name="fileName"> the file name and path of the cache item </param> /// <param name="result"> the content of the cache item to be written </param> /// <param name="url"> the url to write the content for </param> private void WriteToCache(string fileName, byte[] result, Uri url) { if (!this.UseCache || string.IsNullOrEmpty(fileName)) { return; } var cookieList = (from Cookie cookie in this.sessionCookies.GetCookies(url) select new KeyValuePair(cookie.Name, cookie.Value)).ToList(); var cacheItem = new ResponseCacheItem { Content = result, Cookies = cookieList }; Tools.EnsurePathExist(CachePath); using (var file = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { new XmlSerializer(typeof(ResponseCacheItem)).Serialize(file, cacheItem); } }
protected async override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var requestUri = request.RequestUri.ToString(); var requestPath = request.RequestUri.PathAndQuery; var proxyRequestHost = Context.HttpContext.Request.Host; var proxyAddress = $"{Context.HttpContext.Request.Scheme}://{proxyRequestHost}"; var siteSettings = SiteSettings.Current; var sourceAddress = siteSettings.SourceAddress; // Reroute access token requests if (IsAccessTokenRequest(requestPath)) { return(new HttpResponseMessage { Content = new StringContent(await HttpContext.GetTokenAsync("access_token")) }); } if (IsIdTokenRequest(requestPath)) { return(new HttpResponseMessage { Content = new StringContent(await HttpContext.GetTokenAsync("id_token")) }); } // Reroute logout if (IsLogoutRequest(requestPath)) { return(Redirect($"{proxyAddress}/account/logout?returnUrl={WebUtility.UrlEncode(request.Headers.Referrer.ToString() ?? "/")}")); } // Reroute login request to target url (sometimes users are redirected to login if the auth cookie has only just been set) if (IsLoginRequest(requestPath)) { var redirectUri = GetQueryParameter(request.RequestUri.Query, "redirect_to"); if (!string.IsNullOrEmpty(redirectUri)) { return(Redirect(WebUtility.UrlDecode(redirectUri))); } } // Redirect to previously selected language if (IsRootUrl(requestPath) && siteSettings.AutoLanguageRedirect && !(request.Headers.Referrer?.ToString() ?? "").StartsWith(proxyAddress)) { var requestLanguageCookie = GetRequestLanguageCookie(request); if (!string.IsNullOrEmpty(requestLanguageCookie) && requestLanguageCookie != siteSettings.DefaultLanguage) { return(Redirect($"{proxyAddress}/{requestLanguageCookie}")); } } // Modify request headers (for authentication) var wpUserId = await UserService.MapToWpUserAsync(HttpContext.User); request.Headers.Add("X-Wp-Proxy-User-Id", wpUserId.ToString()); request.Headers.Add("X-Wp-Proxy-Key", Settings.ProxyKey); request.Headers.Host = siteSettings.SourceHost; // Determine if content can/should be cached var isDynamicContent = !IsStaticContent(requestUri); var canCache = CanCacheRequest(request) || !isDynamicContent; var isScript = IsScript(requestUri); // Determine cache key var requestKey = canCache ? (request.RequestUri.ToString() + "|" + (isDynamicContent ? wpUserId: 0)) : null; var cacheKey = canCache ? ComputeCacheKeyHash(requestKey) : null; // Load from cache if (canCache) { var responseCacheItem = await Cache.GetAsync <ResponseCacheItem>(cacheKey, refreshOnWPUpdate : isDynamicContent || isScript); if (responseCacheItem != null) { var cachedResponse = await responseCacheItem.ToResponseMessage(FileStore); if (canCache) { SetLanguageCookies(cachedResponse, request, siteSettings.DefaultLanguage); } return(cachedResponse); } } // Execute request if (canCache) { // Remove cookie headers request.Headers.Remove("cookie"); } var response = await base.SendAsync(request, cancellationToken); if (canCache) { // Remove cookie headers response.Headers.Remove("cookie"); response.Headers.Remove("set-cookie"); } if (response.StatusCode == HttpStatusCode.Unauthorized) { return(RedirectToLogin()); } // Handle depending on media type var mediaType = response.Content?.Headers?.ContentType?.MediaType ?? ""; if (IsTextMediaType(mediaType)) { // Text content (documents, json responses etc.) may contain references to // the destination/source address and the content may need to be transformed to // replace these references with the proxy's address // Read content and transform content (replace source address with proxy address) var contentBuilder = new StringBuilder(await response.Content.ReadAsStringAsync()); RewriteUrls(contentBuilder, sourceAddress, proxyAddress); var contentString = contentBuilder.ToString(); response.Content = new StringContent(contentString, Encoding.UTF8, response.Content.Headers.ContentType.MediaType); // Cache content if response is valid for caching if (canCache && ShouldCacheResponse(response)) { // Cache Item (if not already cached) await Cache.GetOrCreateAsync(cacheKey, () => Task.FromResult(ResponseCacheItem.ForTextContent(response, contentString)), refreshOnWPUpdate : true); } } else if (IsMultimediaMediaType(mediaType)) { // Check if response should be cached (e.g not a 500 response or similar) if (canCache && ShouldCacheResponse(response)) { // Read content stream to memory var contentHeaders = response.Content.Headers; var content = await response.Content.ReadAsStreamAsync(); var ms = new MemoryStream(); await content.CopyToAsync(ms); // Save memory stream to disk/storage cache ms.Position = 0; var storageKey = $"{siteSettings.SourceHost}/{cacheKey}"; await FileStore.WriteFileAsync(storageKey, ms); // Create cache entry which references disk/storage await Cache.GetOrCreateAsync(cacheKey, () => Task.FromResult( ResponseCacheItem.ForStreamContent(response, storageKey)), TimeSpan.FromMinutes(15), refreshOnWPUpdate : isDynamicContent ); // Link response to memory stream ms.Position = 0; response.Content = new StreamContent(ms); foreach (var header in contentHeaders) { response.Content.Headers.Add(header.Key, header.Value); } } } RewriteRedirectUrls(response, request, sourceAddress, proxyAddress); if (canCache && isDynamicContent) { SetLanguageCookies(response, request, siteSettings.DefaultLanguage); } return(response); }