Files
KJD/TEMUKJD/Helper/CustomResourceRequestHandlerLocal.cs
T

196 lines
7.6 KiB
C#

using CefSharp;
using CefSharp.Handler;
using CefSharp.ResponseFilter;
using CefSharp.WinForms;
using NaiBa.Util;
using NaiBa.Util.Extension;
using NaiBa.Util.Helper;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace TemuKJD.Helper
{
//public event Action<string, string, string, IRequest> ResourceLoadCompleteEvent; // requestUrl, postData, responseData
public class BaseResourceRequestHandler : ResourceRequestHandler
{
public string UserAgent = string.Empty;
public Func<object, string, string, IRequest, bool> BeforeResourceLoadEvent; // sender, requestUrl, postData, true(表示取消执行)
public Action<object, string, string, string, IRequest> ResourceLoadCompleteEvent; // sender, requestUrl, postData, responseData
public Action<object, string, string, string> 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<ulong, MemoryStream> responseDict = new ConcurrentDictionary<ulong, MemoryStream>();
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);
}
}
}
}