新建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;
评论区