using CefSharp; using CefSharp.Handler; using CefSharp.ResponseFilter; using NaiBa.Util.Helper; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Work._29Tools.CefTools { public class BaseResourceRequestHandler : ResourceRequestHandler { public string UserAgent = string.Empty; public Func BeforeResourceLoadEvent; // sender, requestUrl, postData, true(表示取消执行) public Action ResourceLoadCompleteEvent; // sender, requestUrl, postData, responseData public Action ResourceRedirectEvent; // sender, requestUrl, postData, redirectUrl public string[] ResourceContentTypeRegister = new string[] { "application/json", "javascript", "application/x-www-form-urlencoded", "text/html", "text/plain", "text/event-stream" }; public string GetCharSet(string charSet) { if (string.IsNullOrEmpty(charSet)) { charSet = "UTF-8"; } return charSet; } public string GetPostData(IRequest request) { string postData = string.Empty; if (request.PostData != null && request.PostData.Elements.Any()) { for (int i = 0; i < request.PostData.Elements.Count; i++) { try { string charset = GetCharSet(request.GetCharSet()); if (request.PostData.Elements[i].Type != PostDataElementType.Empty) postData += request.PostData.Elements[i].GetBody(charset); } catch (Exception ex) { LogHelper.WriteWithTime(ex); } } } return postData; } } public class CustomResourceRequestHandlerLocal : BaseResourceRequestHandler { private ConcurrentDictionary responseDict = new ConcurrentDictionary(); 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 (!string.IsNullOrEmpty(UserAgent)) { var headers = request.Headers; headers["User-Agent"] = UserAgent; request.Headers = headers; } //NOTE: If you do not wish to implement this method returning false is the default behaviour // We also suggest you explicitly Dispose of the callback as it wraps an unmanaged resource. //callback.Dispose(); //return false; //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") { try { string postData = GetPostData(request); bool? result = BeforeResourceLoadEvent?.Invoke(chromiumWebBrowser, request.Url, postData, request); } catch (Exception ex) { LogHelper.WriteWithTime(ex); } } } } return CefReturnValue.Continue; } protected override void OnResourceRedirect(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl) { try { if (ResourceRedirectEvent != null) { string postData = GetPostData(request); ResourceRedirectEvent.Invoke(chromiumWebBrowser, request.Url, postData, newUrl); } } catch (Exception ex) { LogHelper.WriteWithTime(ex); } } protected override bool OnProtocolExecution(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request) { return request.Url.StartsWith("mailto"); } protected override bool OnResourceResponse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) { //NOTE: You cannot modify the response, only the request // You can now access the headers //var headers = response.Headers; return false; } protected override IResponseFilter GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) { try { string contentType = response.Headers["Content-Type"]; if (string.IsNullOrEmpty(contentType)) { return null; } if (ResourceContentTypeRegister.Contains(contentType) || ResourceContentTypeRegister.Where(p => contentType.Contains(p)).Any()) { if (ResourceLoadCompleteEvent != null) { MemoryStream memoryStream = new MemoryStream(); responseDict.TryAdd(request.Identifier, memoryStream); return new StreamResponseFilter(memoryStream); } } } catch (Exception ex) { LogHelper.WriteWithTime(ex); } return null; } protected override void OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength) { try { if (responseDict.ContainsKey(request.Identifier)) { MemoryStream memoryStream = null; responseDict.TryRemove(request.Identifier, out memoryStream); if (memoryStream != null) { byte[] data = memoryStream.ToArray(); string charset = GetCharSet(response.Charset); var responseData = Encoding.GetEncoding(charset).GetString(data); string postData = GetPostData(request); ResourceLoadCompleteEvent.Invoke(chromiumWebBrowser, request.Url, postData, responseData, request); } } } catch (Exception ex) { LogHelper.WriteWithTime(ex); } } } }