Пример #1
0
 public void Log <TState>(LogLevel logLevel, EventId eventId, TState state,
                          Exception exception, Func <TState, Exception, string> formatter)
 {
     if (IsEnabled(logLevel))
     {
         Trace.TraceEvent(TraceMapping[logLevel], $"{_categoryName}: {formatter(state, exception)}");
     }
 }
Пример #2
0
        /// <inheritdoc />
        public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context)
        {
#pragma warning disable RCS1163 // Unused parameter.
            // Handle invalid HTTPS certificates and allow alternate security protocols (see http://stackoverflow.com/a/5670954/807064)
            ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;
#pragma warning restore RCS1163 // Unused parameter.

            // Key = link, Value = source, tag HTML
            ConcurrentDictionary <string, ConcurrentBag <(string documentSource, string outerHtml)> > links =
                new ConcurrentDictionary <string, ConcurrentBag <(string documentSource, string outerHtml)> >();

            // Key = source, Value = tag HTML
            ConcurrentDictionary <string, ConcurrentBag <string> > failures = new ConcurrentDictionary <string, ConcurrentBag <string> >();

            // Gather all links
            HtmlParser parser = new HtmlParser();
            context.ParallelForEach(inputs, input => GatherLinks(input, parser, links));

            // This policy will limit the number of executing link validations.
            // Limit the amount of concurrent link checks to avoid overwhelming servers.
            Task[] tasks = links.Select(
                async link =>
            {
                // Attempt to parse the URI
                if (!Uri.TryCreate(link.Key, UriKind.RelativeOrAbsolute, out Uri uri))
                {
                    AddOrUpdateFailure(link.Value, failures);
                }

                // Adjustment for double-slash link prefix which means use http:// or https:// depending on current protocol
                // The Uri class treats these as relative, but they're really absolute
                if (uri.ToString().StartsWith("//") && !Uri.TryCreate($"http:{link.Key}", UriKind.Absolute, out uri))
                {
                    AddOrUpdateFailure(link.Value, failures);
                }

                // Relative
                if (!uri.IsAbsoluteUri && _validateRelativeLinks && !(await ValidateRelativeLink(uri, context).ConfigureAwait(false)))
                {
                    AddOrUpdateFailure(link.Value, failures);
                }

                // Absolute
                if (uri.IsAbsoluteUri && _validateAbsoluteLinks && !(await ValidateAbsoluteLink(uri, context).ConfigureAwait(false)))
                {
                    AddOrUpdateFailure(link.Value, failures);
                }
            }).ToArray();

            Task.WaitAll(tasks);

            // Report failures
            if (failures.Count > 0)
            {
                int    failureCount   = failures.Sum(x => x.Value.Count);
                string failureMessage = string.Join(
                    Environment.NewLine,
                    failures.Select(x => $"{x.Key}{Environment.NewLine} - {string.Join(Environment.NewLine + " - ", x.Value)}"));
                Trace.TraceEvent(
                    _asError ? TraceEventType.Error : TraceEventType.Warning,
                    $"{failureCount} link validation failures:{Environment.NewLine}{failureMessage}");
            }

            return(inputs);
        }
Пример #3
0
        public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context)
        {
            // Handle invalid HTTPS certificates and allow alternate security protocols (see http://stackoverflow.com/a/5670954/807064)
            ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;

            // Key = link, Value = source, tag HTML
            ConcurrentDictionary <string, ConcurrentBag <Tuple <FilePath, string> > > links =
                new ConcurrentDictionary <string, ConcurrentBag <Tuple <FilePath, string> > >();

            // Key = source, Value = tag HTML
            ConcurrentDictionary <FilePath, ConcurrentBag <string> > failures = new ConcurrentDictionary <FilePath, ConcurrentBag <string> >();

            // Gather all links
            HtmlParser parser = new HtmlParser();

            context.ParallelForEach(inputs, input =>
            {
                GatherLinks(input, parser, links);
            });

            // Perform validation
            Parallel.ForEach(links, link =>
            {
                // Attempt to parse the URI
                Uri uri;
                if (!Uri.TryCreate(link.Key, UriKind.RelativeOrAbsolute, out uri))
                {
                    AddOrUpdateFailure(link.Value, failures);
                }

                // Adjustment for double-slash link prefix which means use http:// or https:// depending on current protocol
                // The Uri class treats these as relative, but they're really absolute
                if (uri.ToString().StartsWith("//") && !Uri.TryCreate($"http:{link.Key}", UriKind.Absolute, out uri))
                {
                    AddOrUpdateFailure(link.Value, failures);
                }

                // Relative
                if (!uri.IsAbsoluteUri && _validateRelativeLinks && !ValidateRelativeLink(uri, context))
                {
                    AddOrUpdateFailure(link.Value, failures);
                }

                // Absolute
                if (uri.IsAbsoluteUri && _validateAbsoluteLinks && !ValidateAbsoluteLink(uri, context))
                {
                    AddOrUpdateFailure(link.Value, failures);
                }
            });

            // Report failures
            if (failures.Count > 0)
            {
                int    failureCount   = failures.Sum(x => x.Value.Count);
                string failureMessage = string.Join(Environment.NewLine,
                                                    failures.Select(x => $"{x.Key.FullPath}{Environment.NewLine} - {string.Join(Environment.NewLine + " - ", x.Value)}"));
                Trace.TraceEvent(
                    _asError ? TraceEventType.Error : TraceEventType.Warning,
                    $"{failureCount} link validation failures:{Environment.NewLine}{failureMessage}");
            }

            return(inputs);
        }