Cefsharp 拦截请求响应结果

新建FilterData类

 public class FilterData : IDisposable
    {
        private static ConcurrentDictionary<ulong, MemoryStreamResponseFilter> dataFilters = new();
        /// <summary>
        /// 释放标记
        /// </summary>
        private bool disposed;
        //private ulong Identifier { get; set; }
        //private MemoryStreamResponseFilter memory { get; set; }
        public void AddFilter(ulong Identifier, MemoryStreamResponseFilter memory)
        {
            dataFilters.TryAdd(Identifier, memory);
        }

        public string GetFilter(ulong Identifier)
        {
            dataFilters.TryGetValue(Identifier, out MemoryStreamResponseFilter memory);
            var data = memory?.DataStr;
            memory?.Close();
            dataFilters.TryRemove(Identifier, out MemoryStreamResponseFilter m);
            return data;
        }

        public void Close(ulong Identifier)
        {
            dataFilters.TryGetValue(Identifier, out MemoryStreamResponseFilter memory);
            memory?.Close();
            dataFilters.TryRemove(Identifier, out MemoryStreamResponseFilter m);
            Dispose();
        }

        /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
        public void Dispose()
        {
            //必须为true
            Dispose(true);
            //通知垃圾回收器不再调用终结器
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 非密封类可重写的Dispose方法,方便子类继承时可重写
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
            {
                return;
            }
            //清理托管资源
            if (disposing)
            {

                dataFilters.Clear();
            }

            //告诉自己已经被释放
            disposed = true;
        }

        ///// <summary>
        ///// 为了防止忘记显式的调用Dispose方法
        ///// </summary>
        //~FilterData()
        //{
        //    //必须为false
        //    Dispose(false);
        //}
    }

CustomResourceRequestHandler

    /// <summary>
    /// 返回值拦截
    /// </summary>
    public class CustomResourceRequestHandler : ResourceRequestHandler
    {
        private MemoryStream memoryStream;
        public event EventHandler<OnResourceLoadCompleteEventArgs> OnResourceLoadCompleteEvent;

        public event EventHandler<OnBeforeResourceLoadEventArgs> OnBeforeResourceLoadEvent;
        bool Disposed = false;
        /// <summary>
        /// 是否过滤,如果不过滤就截获
        /// </summary>
        bool filter = false;

        /// <summary>
        /// 过滤、截获 url 列表 和 捕获过滤数据
        /// </summary>
        FilterData filterData { get; set; }

        public CustomResourceRequestHandler(FilterData Filter, bool _filter)
        {
            filterData = Filter;
            filter = _filter;
        }

        protected override CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
        {
            Uri url;
            if (Uri.TryCreate(request.Url, UriKind.Absolute, out url) == false)
            {
                //If we're unable to parse the Uri then cancel the request
                // avoid throwing any exceptions here as we're being called by unmanaged code
                return CefReturnValue.Cancel;
            }

            if (!filter)
            {
                OnBeforeResourceLoadEvent?.Invoke(this,new OnBeforeResourceLoadEventArgs(chromiumWebBrowser, browser, frame, request, callback));
            }

            //NOTE: When executing the callback in an async fashion need to check to see if it's disposed
            //if (!callback.IsDisposed)
            //{
            //    using (callback)
            //    {
            //        if (request.Method == "POST")
            //        {
            //            using (var postData = request.PostData)
            //            {
            //                if (postData != null)
            //                {
            //                    var elements = postData.Elements;
            //                    var charSet = request.GetCharSet();
            //                    foreach (var element in elements)
            //                    {
            //                        if (element.Type == PostDataElementType.Bytes)
            //                        {
            //                            var body = element.GetBody(charSet);
            //                        }
            //                    }
            //                }
            //            }
            //        }
            //    }
            //}
            return base.OnBeforeResourceLoad(chromiumWebBrowser, browser, frame, request, callback);
            //return CefReturnValue.Continue;
        }


        protected override IResponseFilter GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response)
        {
            if (filter) return null;
            var fil = new MemoryStreamResponseFilter(filter);
            filterData.AddFilter(request.Identifier, fil);
            return fil;
        }

        protected override void OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
        {
            var repData = filterData?.GetFilter(request.Identifier);
            filterData?.Close(request.Identifier);
            Debug.WriteLine($"数据输出:-----{repData}");
            OnResourceLoadCompleteEvent?.Invoke(this,new OnResourceLoadCompleteEventArgs(chromiumWebBrowser, browser, frame, request, response, status, receivedContentLength, repData));
        }

        protected override void Dispose()
        {
            if (Disposed)
                return;
            Disposed = true;
        }
    }

MemoryStreamResponseFilter

     public class MemoryStreamResponseFilter : IResponseFilter
    {
        public MemoryStreamResponseFilter(bool _filter) { filter = _filter; }
        bool Disposed = false;
        /// <summary>
        /// 是否过滤,如果不过滤就截获
        /// </summary>
        bool filter = false;

        private MemoryStream memoryStream;
        public void Dispose()
        {
            //memoryStream?.Dispose();
            //memoryStream = null;
            ////必须为true
            //Dispose(true);
            ////通知垃圾回收器不再调用终结器
            //GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool r)
        {
            if (Disposed)
                return;
            if (r)
            {
                memoryStream?.Close();
                memoryStream?.Dispose();
                memoryStream = null;
            }
            Disposed = true;
        }

        public void Close()
        {
            Dispose(true);
        }

        FilterStatus IResponseFilter.Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten)
        {
            try
            {
                if (dataIn == null)
                {
                    dataInRead = 0;
                    dataOutWritten = 0;
                    return FilterStatus.Done;
                }

                dataOutWritten = Math.Min(dataIn.Length, dataOut.Length);
                dataInRead = dataOutWritten;

                byte[] readBytes = new byte[dataOutWritten];
                dataIn.Read(readBytes, 0, (int)dataOutWritten);
                dataOut.Write(readBytes, 0, (int)dataOutWritten);

                //copy data to filter memory stream
                memoryStream.Write(readBytes, 0, (int)dataOutWritten);

                return dataOutWritten < dataIn.Length ? FilterStatus.NeedMoreData : FilterStatus.Done;
            }
            catch (Exception e)
            {
                Logger.Default.Error($"IResponseFilter处理出错:{e.Message}");
                dataInRead = dataIn.Length;
                dataOutWritten = dataIn.Length;
                return FilterStatus.Done;
            }
        }

        bool IResponseFilter.InitFilter()
        {
            memoryStream = new MemoryStream();
            return true;
        }
        public byte[] Data
        {
            get
            {
                var data = memoryStream.ToArray();
                memoryStream?.Close();
                memoryStream?.Dispose();
                return data;
            }
        }

        public string DataStr
        {
            get
            {
                var data = Encoding.UTF8.GetString(memoryStream.ToArray());
                memoryStream?.Close();
                memoryStream?.Dispose();
                return data;
            }
        }

        //~MemoryStreamResponseFilter()
        //{
        //    //必须false
        //    Dispose(false);
        //}
    }

这里会汲级内存无法扩容参考:https://github.com/cefsharp/CefSharp/issues/2433

新建RequestEventHandler类并在此类中调用CustomResourceRequestHandler

   public class RequestEventHandler : RequestHandler

    {
        public event EventHandler<OnBeforeBrowseEventArgs> OnBeforeBrowseEvent;
        public event EventHandler<OnOpenUrlFromTabEventArgs> OnOpenUrlFromTabEvent;
        public event EventHandler<OnCertificateErrorEventArgs> OnCertificateErrorEvent;
        public event EventHandler<OnPluginCrashedEventArgs> OnPluginCrashedEvent;
        public event EventHandler<GetAuthCredentialsEventArgs> GetAuthCredentialsEvent;
        public event EventHandler<OnRenderProcessTerminatedEventArgs> OnRenderProcessTerminatedEvent;
        public event EventHandler<OnQuotaRequestEventArgs> OnQuotaRequestEvent;
        public event EventHandler<System.EventArgs> requestEvent;

        public event EventHandler<System.EventArgs> UpdateRequestEvent;
        public bool Isintercept { get; set; } = false;

        protected override bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
        {
            var args = new OnBeforeBrowseEventArgs(chromiumWebBrowser, browser, frame, request, userGesture, isRedirect);

            OnBeforeBrowseEvent?.Invoke(this, args);

            return args.CancelNavigation;
        }

        protected override bool OnOpenUrlFromTab(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
        {
            var args = new OnOpenUrlFromTabEventArgs(chromiumWebBrowser, browser, frame, targetUrl, targetDisposition, userGesture);

            OnOpenUrlFromTabEvent?.Invoke(this, args);

            return args.CancelNavigation;
        }

        protected override bool OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback)
        {
            var args = new OnCertificateErrorEventArgs(chromiumWebBrowser, browser, errorCode, requestUrl, sslInfo, callback);

            OnCertificateErrorEvent?.Invoke(this, args);

            EnsureCallbackDisposal(callback);
            return args.ContinueAsync;
        }

        protected override void OnPluginCrashed(IWebBrowser chromiumWebBrowser, IBrowser browser, string pluginPath)
        {
            var args = new OnPluginCrashedEventArgs(chromiumWebBrowser, browser, pluginPath);

            OnPluginCrashedEvent?.Invoke(this, args);
        }

        protected override bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
        {
            var args = new GetAuthCredentialsEventArgs(chromiumWebBrowser, browser, originUrl, isProxy, host, port, realm, scheme, callback);

            GetAuthCredentialsEvent?.Invoke(this, args);

            EnsureCallbackDisposal(callback);
            return args.ContinueAsync;
        }

        /// <summary>
        /// 线程终止
        /// </summary>
        /// <param name="chromiumWebBrowser"></param>
        /// <param name="browser"></param>
        /// <param name="status"></param>
        protected override void OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status)
        {
            var args = new OnRenderProcessTerminatedEventArgs(chromiumWebBrowser, browser, status);

            OnRenderProcessTerminatedEvent?.Invoke(this, args);
        }

        protected override bool OnQuotaRequest(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, long newSize, IRequestCallback callback)
        {
            var args = new OnQuotaRequestEventArgs(chromiumWebBrowser, browser, originUrl, newSize, callback);
            OnQuotaRequestEvent?.Invoke(this, args);

            EnsureCallbackDisposal(callback);
            return args.ContinueAsync;
        }

        /// <summary>
        /// 拦截请求
        /// </summary>
        /// <param name="chromiumWebBrowser"></param>
        /// <param name="browser"></param>
        /// <param name="frame"></param>
        /// <param name="request"></param>
        /// <param name="isNavigation"></param>
        /// <param name="isDownload"></param>
        /// <param name="requestInitiator"></param>
        /// <param name="disableDefaultHandling"></param>
        /// <returns></returns>
        protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame,
            IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
        {
            if (Isintercept)
            {
                //requestEvent?.Invoke(request, new System.EventArgs());
                var resource = new CustomResourceRequestHandler(new FilterData(), false);
                resource.OnBeforeResourceLoadEvent += (e, args) =>
                {
                    UpdateRequestEvent?.Invoke(this, args);
                };

                resource.OnResourceLoadCompleteEvent += (e, args) =>
                {
                    requestEvent?.Invoke(this, args);
                };
                return resource;
            }

            return base.GetResourceRequestHandler(
                    chromiumWebBrowser, browser, frame, request, isNavigation,
                    isDownload, requestInitiator, ref disableDefaultHandling);

            // 先调用基类的实现,断点调试
        }

        private static void EnsureCallbackDisposal(IRequestCallback callbackToDispose)
        {
            if (callbackToDispose != null && !callbackToDispose.IsDisposed)
            {
                callbackToDispose.Dispose();
            }
        }

        private static void EnsureCallbackDisposal(IAuthCallback callbackToDispose)
        {
            if (callbackToDispose != null && !callbackToDispose.IsDisposed)
            {
                callbackToDispose.Dispose();
            }
        }
    }

 使用:

 _customRequestHandler = new RequestEventHandler();
 chromeBrowser.RequestHandler = _customRequestHandler;


本文作者:admin

本文链接:https://www.javalc.com/post/91.html

版权声明:本篇文章于2022-03-10,由admin发表,转载请注明出处:分享你我。如有疑问,请联系我们

CefSharp 滑动、输入、获取标签位置、点击等封装(支持XPath语法操作)

发表评论

取消
扫码支持