Exemple #1
0
        /// <summary>
        /// If CDN is enabled for this request, replace the outgoing media url with the cdn version
        /// </summary>
        /// <param name="item"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public override string GetMediaUrl(Sitecore.Data.Items.MediaItem item, MediaUrlOptions options)
        {
            string hostname = CDNManager.GetCDNHostName();
            string url      = base.GetMediaUrl(item, options);

            bool shouldReplace = !string.IsNullOrEmpty(hostname) &&           // cdnHostname exists for site
                                 Sitecore.Context.PageMode.IsNormal;          // PageMode is normal

            bool dontReplace = !CDNManager.IsMediaPubliclyAccessible(item) || // media is publicly accessible
                               CDNManager.IsMediaAnalyticsTracked(item);      // media is analytics tracked

            CDNUrlState contextState = CDNUrlSwitcher.CurrentValue;

            if (contextState == CDNUrlState.Enabled)
            {
                shouldReplace = true;
            }
            else if (contextState == CDNUrlState.Disabled)
            {
                UrlString url2 = new UrlString(url);
                url2[CDNManager.StopToken] = "1";
                url           = url2.ToString();
                shouldReplace = false;
            }


            if (shouldReplace && !dontReplace) // media not DMS tracked
            {
                return(CDNManager.ReplaceMediaUrl(url, hostname));
            }
            else
            {
                return(url);
            }
        }
        public override void Process(HttpRequestArgs args)
        {
            Assert.ArgumentNotNull(args, "args");

            if (!CDNSettings.Enabled)
            {
                return;
            }

            bool shouldFilter = (Sitecore.Context.Item != null || CDNManager.ShouldProcessRequest(args.Url.FilePathWithQueryString)) && // if an item is resolved (this is a page request) or file ext is listed in <processRequests>
                                !CDNManager.ShouldExcludeProcessRequest(args.Url.FilePathWithQueryString) &&                            // if the url is not on the excluded list
                                Sitecore.Context.Site != null &&                                                                        // and a site was resolved
                                Sitecore.Context.PageMode.IsNormal &&                                                                   // and the site is not in editing mode
                                !string.IsNullOrEmpty(CDNManager.GetCDNHostName());                                                     // and the current site is not in the excluded sites list

            // querystring cdn=1  to force replacement
            // querystring cdn=0  to force no replacement
            Tristate force = MainUtil.GetTristate(WebUtil.GetQueryString("cdn"), Tristate.Undefined);

            if (force == Tristate.False)
            {
                shouldFilter = false;
            }
            else if (force == Tristate.True)
            {
                shouldFilter = true;
            }

            if (shouldFilter)
            {
                var response = HttpContext.Current.Response;
                if (response != null)
                {
                    // replace the default response filter stream with our replacer filter
                    response.Filter = new MediaUrlFilter(response.Filter);
                }
            }
        }
        /// <summary>
        /// This Method buffers the original Write payloads until the end of the end [/html] tag
        /// when replacement occurs
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public override void Write(byte[] buffer, int offset, int count)
        {
            // preview the contents of the payload
            string content = UTF8Encoding.UTF8.GetString(buffer, offset, count);

            Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);

            // if the content contains </html> we know we're at the end of the line
            // otherwise append the contents to the stringbuilder
            if (!eof.IsMatch(content))
            {
                if (_isComplete)
                {
                    _responseStream.Write(buffer, offset, count);
                }
                else
                {
                    _sb.Append(content);
                }
            }
            else
            {
                _sb.Append(content.Substring(0, content.IndexOf("</html>") + 7));

                string extra = content.Substring(content.IndexOf("</html>") + 7);

                try
                {
                    using (new TimerReport("replaceMediaUrls"))
                    {
                        // parse complete document into HtmlDocument
                        HtmlDocument doc = new HtmlDocument();
                        doc.LoadHtml(_sb.ToString());

                        if (CDNSettings.DebugParser)
                        {
                            var parseErrors = doc.ParseErrors;
                            if (parseErrors != null)
                            {
                                parseErrors = parseErrors.Where(pe => pe.Code == HtmlParseErrorCode.EndTagInvalidHere || pe.Code == HtmlParseErrorCode.TagNotClosed || pe.Code == HtmlParseErrorCode.TagNotOpened);
                            }

                            if (parseErrors != null && parseErrors.Any())
                            {
                                StringBuilder sb = new StringBuilder();
                                foreach (var parseError in parseErrors)
                                {
                                    sb.AppendLine(string.Format("PARSE ERROR: {0}", parseError.Reason));
                                    sb.AppendLine(string.Format("Line: {0} Position: {1}", parseError.Line, parseError.LinePosition));
                                    sb.AppendLine(string.Format("Source: {0}", parseError.SourceText));
                                    sb.AppendLine("");
                                }

                                Log.Error(string.Format("CDN Url Parsing Error - URL: {0} {1} {2}", WebUtil.GetRawUrl(), Environment.NewLine, sb.ToString()), this);
                            }
                        }
                        // replace appropriate urls
                        CDNManager.ReplaceMediaUrls(doc);

                        StreamWriter writer = new StreamWriter(_responseStream);
                        doc.Save(writer);
                        writer.Flush();
                    }
                    _isComplete = true;
                }
                catch (Exception ex)
                {
                    Log.Error("CDN MediaURL Filter Error", ex, this);
                }

                if (!string.IsNullOrEmpty(extra))
                {
                    byte[] data = UTF8Encoding.UTF8.GetBytes(extra);
                    _responseStream.Write(data, 0, data.Length);
                }
            }
        }
Exemple #4
0
        public void ProcessRequest(HttpContext context)
        {
            // set from an earlier in pipeline by CDNInterceptPipeline
            string minifyPath = StringUtil.GetString(context.Items["MinifyPath"]);

            if (string.IsNullOrEmpty(minifyPath))
            {
                context.Response.StatusCode = 404;
                context.Response.End();
            }


            UrlString url       = new UrlString(minifyPath);
            string    localPath = url.Path;

            string filePath = FileUtil.MapPath(localPath);

            // if the request is a .js file
            if (localPath.EndsWith(".js"))
            {
                HashEncryption hasher = new HashEncryption(HashEncryption.EncryptionProvider.MD5);
                if (!string.IsNullOrEmpty(localPath))
                {
                    // generate a unique filename for the cached .js version
                    string cachedFilePath = FileUtil.MapPath(string.Format("/App_Data/MediaCache/{0}.js", hasher.Hash(url.ToString())));

                    // if it doesn't exist create it
                    if (!FileUtil.FileExists(cachedFilePath))
                    {
                        // if the original file exsits minify it
                        if (FileUtil.FileExists(filePath))
                        {
                            JsMinifier minifier = new JsMinifier();
                            string     minified = minifier.Minify(filePath);
                            FileUtil.WriteToFile(cachedFilePath, minified);
                        }
                    }

                    if (FileUtil.FileExists(cachedFilePath))
                    {
                        context.Response.ClearHeaders();
                        context.Response.Cache.SetExpires(DateTime.Now.AddDays(14));
                        context.Response.AddHeader("Content-Type", "application/x-javascript; charset=utf-8");
                        context.Response.WriteFile(cachedFilePath);
                        context.Response.End();
                        _success = true;
                    }
                }
            }
            // if the request is a .css file
            else if (localPath.EndsWith(".css"))
            {
                HashEncryption hasher = new HashEncryption(HashEncryption.EncryptionProvider.MD5);
                if (!string.IsNullOrEmpty(localPath))
                {
                    // generate a unique filename for the cached .css version
                    string cachedFilePath = FileUtil.MapPath(string.Format("/App_Data/MediaCache/{0}.css", hasher.Hash(url.ToString())));

                    // if it doesn't exist create it
                    if (!FileUtil.FileExists(cachedFilePath))
                    {
                        // if the original file exsits minify it
                        if (FileUtil.FileExists(filePath))
                        {
                            CssMinifier minifier = new CssMinifier();
                            string      minified = CssMinifier.Minify(FileUtil.ReadFromFile(filePath));

                            // if Css Processing is enabled, replace any urls inside the css file.
                            if (CDNSettings.ProcessCss)
                            {
                                // find all css occurences of url([url])
                                Regex reReplaceUrl = new Regex("url\\(\\s*['\"]?([^\"')]+)['\"]?\\s*\\)");

                                try
                                {
                                    // replacing  url([url]) with url([cdnUrl]) in css
                                    minified = reReplaceUrl.Replace(minified, (m) =>
                                    {
                                        string oldUrl = "";
                                        if (m.Groups.Count > 1)
                                        {
                                            oldUrl = m.Groups[1].Value;
                                        }

                                        if (WebUtil.IsInternalUrl(oldUrl))
                                        {
                                            if (oldUrl.StartsWith("."))
                                            {
                                                oldUrl = VirtualPathUtility.Combine(url.Path, oldUrl);
                                            }
                                            string newUrl = CDNManager.ReplaceMediaUrl(oldUrl, string.Empty);
                                            if (!string.IsNullOrEmpty(newUrl))
                                            {
                                                return(m.Value.Replace(m.Groups[1].Value, newUrl));
                                            }
                                        }

                                        return(m.Value);
                                    });
                                }
                                catch (Exception ex)
                                {
                                    Log.Error("Minify error", ex, this);
                                }
                            }

                            FileUtil.WriteToFile(cachedFilePath, minified);
                        }
                    }

                    if (FileUtil.FileExists(cachedFilePath))
                    {
                        context.Response.ClearHeaders();
                        context.Response.Cache.SetExpires(DateTime.Now.AddDays(14));
                        context.Response.AddHeader("Content-Type", "text/css; charset=utf-8");
                        context.Response.TransmitFile(cachedFilePath);
                        context.Response.End();
                        _success = true;
                    }
                }
            }
        }