public DefaultNonCachedLessCssLoaderFactory(
     IRelativePathMapper pathMapper,
     SourceMappingMarkerInjectionOptions sourceMappingMarkerInjection,
     ErrorBehaviourOptions errorBehaviour,
     ILogEvents logger)
     : this(new SimpleTextFileContentLoader(pathMapper), sourceMappingMarkerInjection, errorBehaviour, logger)
 {
 }
        public SingleFileLastModifiedDateRetriever(IRelativePathMapper relativePathMapper)
        {
            if (relativePathMapper == null)
            {
                throw new ArgumentNullException("relativePathMapper");
            }

            _relativePathMapper = relativePathMapper;
        }
        public SimpleTextFileContentLoader(IRelativePathMapper relativePathMapper)
        {
            if (relativePathMapper == null)
            {
                throw new ArgumentNullException("relativePathMapper");
            }

            _relativePathMapper = relativePathMapper;
        }
        public SingleFolderLastModifiedDateRetriever(IRelativePathMapper relativePathMapper, IEnumerable <string> optionalExtensionRestrictions)
        {
            if (relativePathMapper == null)
            {
                throw new ArgumentNullException("relativePathMapper");
            }

            if (optionalExtensionRestrictions == null)
            {
                _extensionRestrictions = new[] { "*" }
            }
            ;
            else
            {
                var optionalExtensionRestrictionsTidied = optionalExtensionRestrictions.ToList();
                if (optionalExtensionRestrictionsTidied.Any(e => string.IsNullOrWhiteSpace(e)))
                {
                    throw new ArgumentException("Encountered null or blank entry in optionalExtensionRestrictions set");
                }
                _extensionRestrictions = optionalExtensionRestrictionsTidied.Select(e => e.Trim().ToLower()).Distinct().ToArray();
            }

            _relativePathMapper = relativePathMapper;
        }
 public DefaultNonCachedLessCssLoaderFactory(IRelativePathMapper pathMapper)
     : this(new SimpleTextFileContentLoader(pathMapper), SourceMappingMarkerInjectionOptions.Inject, ErrorBehaviourOptions.LogAndRaiseException, new NullLogger())
 {
 }
Ejemplo n.º 6
0
        /// <summary>
        /// This will combine a stylesheet with all of its imports (and any imports within those, and within those, etc..) and minify the resulting content for cases only
        /// where all files are in the same folder and no relative or absolute paths are specified in the import declarations. It incorporates caching of the minified
        /// content and implements 304 responses for cases where the request came with an If-Modified-Since header indicating that current content already exists on the
        /// client. The last-modified-date for the content is determined by retrieving the most recent LastWriteTime for any file in the folder - although this may lead
        /// to some false-positives if unrelated files are updated, it does mean that if any file that IS part of the combined stylesheet is updated then the content
        /// will be identified as stale and re-generated. The cached content will likewise be invalidated and updated if any files in the folder have changed since the
        /// date recorded for the cached data. GZip and Deflate compression of the response are supported where specified in Accept-Encoding request headers.
        /// </summary>
        private ActionResult Process(
            string relativePath,
            IRelativePathMapper relativePathMapper,
            ICacheThingsWithModifiedDates <TextFileContents> memoryCache,
            DateTime?lastModifiedDateFromRequest)
        {
            if (string.IsNullOrWhiteSpace(relativePath))
            {
                throw new ArgumentException("Null/blank relativePath specified");
            }
            if (memoryCache == null)
            {
                throw new ArgumentNullException(nameof(memoryCache));
            }
            if (relativePathMapper == null)
            {
                throw new ArgumentNullException(nameof(relativePathMapper));
            }

            // Using the SingleFolderLastModifiedDateRetriever means that we can determine whether cached content (either in the ASP.Net cache or in the browser cache)
            // is up to date without having to perform the complete import flattening process. It may lead to some unnecessary work if an unrelated file in the folder
            // is updated but for the most common cases it should be an efficient approach.
            var lastModifiedDateRetriever = new SingleFolderLastModifiedDateRetriever(relativePathMapper, new[] { "css", "less" });
            var lastModifiedDate          = lastModifiedDateRetriever.GetLastModifiedDate(relativePath);

            if ((lastModifiedDateFromRequest != null) && AreDatesApproximatelyEqual(lastModifiedDateFromRequest.Value, lastModifiedDate))
            {
                Response.StatusCode = 304;
                return(Content("Not changed since last request", "text/css"));
            }

            var cssLoader = (new EnhancedNonCachedLessCssLoaderFactory(
                                 relativePathMapper,
                                 SourceMappingMarkerInjectionOptions.Inject,
                                 ErrorBehaviourOptions.LogAndRaiseException,
                                 new CSSMinifier.Logging.NullLogger()
                                 )).Get();

            // Ignore any errors from the DiskCachingTextFileLoader - if the file contents become invalid then allow them to be deleted and rebuilt instead of blowing
            // up. The EnhancedNonCachedLessCssLoaderFactory should raise exceptionns since it will indicate invalid source content, which should be flagged up.
            var modifiedDateCachingStyleLoader = new CachingTextFileLoader(
                new DiskCachingTextFileLoader(
                    cssLoader,
                    relativePathRequested => new FileInfo(relativePathMapper.MapPath(relativePathRequested) + ".cache"),
                    lastModifiedDateRetriever,
                    DiskCachingTextFileLoader.InvalidContentBehaviourOptions.Delete,
                    ErrorBehaviourOptions.LogAndContinue,
                    new CSSMinifier.Logging.NullLogger()
                    ),
                lastModifiedDateRetriever,
                memoryCache
                );

            var content = modifiedDateCachingStyleLoader.Load(relativePath);

            if (content == null)
            {
                throw new Exception("Received null response from Css Loader - this should not happen");
            }
            if ((lastModifiedDateFromRequest != null) && AreDatesApproximatelyEqual(lastModifiedDateFromRequest.Value, lastModifiedDate))
            {
                Response.StatusCode = 304;
                return(Content("Not changed since last request", "text/css"));
            }
            SetResponseCacheHeadersForSuccess(content.LastModified);
            return(Content(content.Content, "text/css"));
        }
 public SingleFolderLastModifiedDateRetriever(IRelativePathMapper relativePathMapper) : this(relativePathMapper, null)
 {
 }