/// <summary>
        /// Checks if the given response can be cached. http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4
        /// </summary>
        /// <returns>Returns true if cacheable, false otherwise.</returns>
        internal static bool IsCacheble(Uri uri, HTTPMethods method, HTTPResponse response)
        {
            if (method != HTTPMethods.Get)
                return false;

            if (response == null)
                return false;

            // Already cached
            if (response.StatusCode == 304)
                return false;

            if (response.StatusCode < 200 || response.StatusCode >= 400)
                return false;

            //http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.2
            var cacheControls = response.GetHeaderValues("cache-control");
            if (cacheControls != null && cacheControls[0].ToLower().Contains("no-store"))
                return false;

            var pragmas = response.GetHeaderValues("pragma");
            if (pragmas != null && pragmas[0].ToLower().Contains("no-cache"))
                return false;

            // Responses with byte ranges not supported yet.
            var byteRanges = response.GetHeaderValues("content-range");
            if (byteRanges != null)
                return false;

            return true;
        }
Exemple #2
0
        /// <summary>
        /// Will set or update all cookies from the response object.
        /// </summary>
        internal static void Set(HTTPResponse response)
        {
            if (response == null)
            {
                return;
            }

            lock (Locker)
            {
                try
                {
                    Maintain();

                    List <Cookie> newCookies       = new List <Cookie>();
                    var           setCookieHeaders = response.GetHeaderValues("set-cookie");

                    // No cookies. :'(
                    if (setCookieHeaders == null)
                    {
                        return;
                    }

                    foreach (var cookieHeader in setCookieHeaders)
                    {
                        try
                        {
                            Cookie cookie = Cookie.Parse(cookieHeader, response.baseRequest.CurrentUri);

                            if (cookie != null)
                            {
                                int idx;
                                var old = Find(cookie, out idx);

                                // if no value for the cookie or already expired then the server asked us to delete the cookie
                                bool expired = string.IsNullOrEmpty(cookie.Value) || !cookie.WillExpireInTheFuture();

                                if (!expired)
                                {
                                    // no old cookie, add it straith to the list
                                    if (old == null)
                                    {
                                        Cookies.Add(cookie);

                                        newCookies.Add(cookie);
                                    }
                                    else
                                    {
                                        // Update the creation-time of the newly created cookie to match the creation-time of the old-cookie.
                                        cookie.Date  = old.Date;
                                        Cookies[idx] = cookie;

                                        newCookies.Add(cookie);
                                    }
                                }
                                else if (idx != -1) // delete the cookie
                                {
                                    Cookies.RemoveAt(idx);
                                }
                            }
                        }
                        catch
                        {
                            // Ignore cookie on error
                        }
                    }

                    response.Cookies = newCookies;
                }
                catch
                {}
            }
        }
        /// <summary>
        /// Checks if the given response can be cached. http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4
        /// </summary>
        /// <returns>Returns true if cacheable, false otherwise.</returns>
        internal static bool IsCacheble(Uri uri, HTTPMethods method, HTTPResponse response)
        {
            if (!IsSupported)
            {
                return(false);
            }

            if (method != HTTPMethods.Get)
            {
                return(false);
            }

            if (response == null)
            {
                return(false);
            }

            // Already cached
            if (response.StatusCode == 304)
            {
                return(false);
            }

            if (response.StatusCode < 200 || response.StatusCode >= 400)
            {
                return(false);
            }

            //http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.2
            var cacheControls = response.GetHeaderValues("cache-control");

            if (cacheControls != null)
            {
                if (cacheControls.Exists(headerValue => {
                    string value = headerValue.ToLower();
                    return(value.Contains("no-store") || value.Contains("no-cache"));
                }))
                {
                    return(false);
                }
            }

            var pragmas = response.GetHeaderValues("pragma");

            if (pragmas != null)
            {
                if (pragmas.Exists(headerValue => {
                    string value = headerValue.ToLower();
                    return(value.Contains("no-store") || value.Contains("no-cache"));
                }))
                {
                    return(false);
                }
            }

            // Responses with byte ranges not supported yet.
            var byteRanges = response.GetHeaderValues("content-range");

            if (byteRanges != null)
            {
                return(false);
            }

            return(true);
        }
Exemple #4
0
        /// <summary>
        /// Checks if the given response can be cached. http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4
        /// </summary>
        /// <returns>Returns true if cacheable, false otherwise.</returns>
        internal static bool IsCacheble(Uri uri, HTTPMethods method, HTTPResponse response)
        {
            if (!IsSupported)
            {
                return(false);
            }

            if (method != HTTPMethods.Get)
            {
                return(false);
            }

            if (response == null)
            {
                return(false);
            }

            // https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.12 - Cache Replacement
            // It MAY insert it into cache storage and MAY, if it meets all other requirements, use it to respond to any future requests that would previously have caused the old response to be returned.
            //if (response.StatusCode == 304)
            //    return false;

            if (response.StatusCode < 200 || response.StatusCode >= 400)
            {
                return(false);
            }

            //http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.2
            var cacheControls = response.GetHeaderValues("cache-control");

            if (cacheControls != null)
            {
                if (cacheControls.Exists(headerValue => {
                    string value = headerValue.ToLower();
                    return(value.Contains("no-store") || value.Contains("no-cache"));
                }))
                {
                    return(false);
                }
            }

            var pragmas = response.GetHeaderValues("pragma");

            if (pragmas != null)
            {
                if (pragmas.Exists(headerValue => {
                    string value = headerValue.ToLower();
                    return(value.Contains("no-store") || value.Contains("no-cache"));
                }))
                {
                    return(false);
                }
            }

            // Responses with byte ranges not supported yet.
            var byteRanges = response.GetHeaderValues("content-range");

            if (byteRanges != null)
            {
                return(false);
            }

            return(true);
        }
Exemple #5
0
        internal void SetUpCachingValues(HTTPResponse response)
        {
            response.CacheFileInfo = this;

            this.ETag         = response.GetFirstHeaderValue("ETag").ToStr(this.ETag ?? string.Empty);
            this.Expires      = response.GetFirstHeaderValue("Expires").ToDateTime(this.Expires);
            this.LastModified = response.GetFirstHeaderValue("Last-Modified").ToStr(this.LastModified ?? string.Empty);

            this.Age = response.GetFirstHeaderValue("Age").ToInt64(this.Age);

            this.Date = response.GetFirstHeaderValue("Date").ToDateTime(this.Date);

            List <string> cacheControls = response.GetHeaderValues("cache-control");

            if (cacheControls != null && cacheControls.Count > 0)
            {
                // Merge all Cache-Control header values into one
                string cacheControl = cacheControls[0];
                for (int i = 1; i < cacheControls.Count; ++i)
                {
                    cacheControl += "," + cacheControls[i];
                }

                if (!string.IsNullOrEmpty(cacheControl))
                {
                    string[] options = cacheControl.ToLowerInvariant().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                    string[] kvp = options.FindOption("max-age");
                    if (kvp != null)
                    {
                        // Some cache proxies will return float values
                        double maxAge;
                        if (double.TryParse(kvp[1], out maxAge))
                        {
                            this.MaxAge = (int)maxAge;
                        }
                        else
                        {
                            this.MaxAge = 0;
                        }
                    }
                    else
                    {
                        this.MaxAge = 0;
                    }

                    kvp = options.FindOption("stale-while-revalidate");
                    if (kvp != null && kvp.Length == 2 && !string.IsNullOrEmpty(kvp[1]))
                    {
                        this.StaleWhileRevalidate = kvp[1].ToInt64(0);
                    }

                    kvp = options.FindOption("stale-if-error");
                    if (kvp != null && kvp.Length == 2 && !string.IsNullOrEmpty(kvp[1]))
                    {
                        this.StaleIfError = kvp[1].ToInt64(0);
                    }

                    this.MustRevalidate = cacheControl.Contains("must-revalidate");
                    this.NoCache        = cacheControl.Contains("no-cache");
                }
            }

            this.Received = DateTime.UtcNow;
        }
Exemple #6
0
        /// <summary>
        /// Checks if the given response can be cached. http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4
        /// </summary>
        /// <returns>Returns true if cacheable, false otherwise.</returns>
        internal static bool IsCacheble(Uri uri, HTTPMethods method, HTTPResponse response)
        {
            if (!IsSupported)
            {
                return(false);
            }

            if (method != HTTPMethods.Get)
            {
                return(false);
            }

            if (response == null)
            {
                return(false);
            }

            // https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.12 - Cache Replacement
            // It MAY insert it into cache storage and MAY, if it meets all other requirements, use it to respond to any future requests that would previously have caused the old response to be returned.
            //if (response.StatusCode == 304)
            //    return false;

            // Partial response
            if (response.StatusCode == 206)
            {
                return(false);
            }

            if (response.StatusCode < 200 || response.StatusCode >= 400)
            {
                return(false);
            }

            //http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.2
            var cacheControls = response.GetHeaderValues("cache-control");

            if (cacheControls != null)
            {
                if (cacheControls.Exists(headerValue =>
                {
                    string value = headerValue.ToLower();
                    if (value.StartsWith("max-age"))
                    {
                        string[] kvp = headerValue.FindOption("max-age");
                        if (kvp != null)
                        {
                            // Some cache proxies will return float values
                            double maxAge;
                            if (double.TryParse(kvp[1], out maxAge))
                            {
                                // A negative max-age value is a no cache
                                if (maxAge <= 0)
                                {
                                    return(false);
                                }
                            }
                        }
                    }

                    // https://csswizardry.com/2019/03/cache-control-for-civilians/#no-store
                    return(value.Contains("no-store"));
                }))
                {
                    return(false);
                }
            }

            var pragmas = response.GetHeaderValues("pragma");

            if (pragmas != null)
            {
                if (pragmas.Exists(headerValue =>
                {
                    string value = headerValue.ToLower();
                    return(value.Contains("no-store") || value.Contains("no-cache"));
                }))
                {
                    return(false);
                }
            }

            // Responses with byte ranges not supported yet.
            var byteRanges = response.GetHeaderValues("content-range");

            if (byteRanges != null)
            {
                return(false);
            }

            // Store only if at least one caching header with proper value present

            var etag = response.GetFirstHeaderValue("ETag");

            if (!string.IsNullOrEmpty(etag))
            {
                return(true);
            }

            var expires = response.GetFirstHeaderValue("Expires").ToDateTime(DateTime.FromBinary(0));

            if (expires >= DateTime.UtcNow)
            {
                return(true);
            }

            if (response.GetFirstHeaderValue("Last-Modified") != null)
            {
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Will set or update all cookies from the response object.
        /// </summary>
        internal static void Set(HTTPResponse response)
        {
            if (response == null)
                return;

            lock(Locker)
            {
                try
                {
                    Maintain();

                    List<Cookie> newCookies = new List<Cookie>();
                    var setCookieHeaders = response.GetHeaderValues("set-cookie");

                    // No cookies. :'(
                    if (setCookieHeaders == null)
                        return;

                    foreach (var cookieHeader in setCookieHeaders)
                    {
                        try
                        {
                            Cookie cookie = Cookie.Parse(cookieHeader, response.baseRequest.CurrentUri);

                            if (cookie != null)
                            {
                                int idx;
                                var old = Find(cookie, out idx);

                                // if no value for the cookie or already expired then the server asked us to delete the cookie
                                bool expired = string.IsNullOrEmpty(cookie.Value) || !cookie.WillExpireInTheFuture();

                                if (!expired)
                                {
                                    // no old cookie, add it straith to the list
                                    if (old == null)
                                    {
                                        Cookies.Add(cookie);

                                        newCookies.Add(cookie);
                                    }
                                    else
                                    {
                                        // Update the creation-time of the newly created cookie to match the creation-time of the old-cookie.
                                        cookie.Date = old.Date;
                                        Cookies[idx] = cookie;

                                        newCookies.Add(cookie);
                                    }
                                }
                                else if (idx != -1) // delete the cookie
                                    Cookies.RemoveAt(idx);
                            }
                        }
                        catch
                        {
                            // Ignore cookie on error
                        }
                    }

                    response.Cookies = newCookies;
                }
                catch
                {}
            }
        }
Exemple #8
0
        /// <summary>
        /// Will set or update all cookies from the response object.
        /// </summary>
        internal static bool Set(HTTPResponse response)
        {
            if (response == null)
            {
                return(false);
            }

            List <Cookie> newCookies       = new List <Cookie>();
            var           setCookieHeaders = response.GetHeaderValues("set-cookie");

            // No cookies. :'(
            if (setCookieHeaders == null)
            {
                return(false);
            }

            foreach (var cookieHeader in setCookieHeaders)
            {
                Cookie cookie = Cookie.Parse(cookieHeader, response.baseRequest.CurrentUri, response.baseRequest.Context);
                if (cookie != null)
                {
                    rwLock.EnterWriteLock();
                    try
                    {
                        int idx;
                        var old = Find(cookie, out idx);

                        // if no value for the cookie or already expired then the server asked us to delete the cookie
                        bool expired = string.IsNullOrEmpty(cookie.Value) || !cookie.WillExpireInTheFuture();

                        if (!expired)
                        {
                            // no old cookie, add it straight to the list
                            if (old == null)
                            {
                                Cookies.Add(cookie);

                                newCookies.Add(cookie);
                            }
                            else
                            {
                                // Update the creation-time of the newly created cookie to match the creation-time of the old-cookie.
                                cookie.Date  = old.Date;
                                Cookies[idx] = cookie;

                                newCookies.Add(cookie);
                            }
                        }
                        else if (idx != -1) // delete the cookie
                        {
                            Cookies.RemoveAt(idx);
                        }
                    }
                    catch
                    {
                        // Ignore cookie on error
                    }
                    finally
                    {
                        rwLock.ExitWriteLock();
                    }
                }
            }

            response.Cookies = newCookies;

            PluginEventHelper.EnqueuePluginEvent(new PluginEventInfo(PluginEvents.SaveCookieLibrary));

            return(true);
        }