当前位置: 首页 > news >正文

成都营销型网站制作黑色网站后台

成都营销型网站制作,黑色网站后台,昆明网站建设价目表,领动做的网站怎么样前言在CefSharp中#xff0c;我们不仅可以使用Chromium浏览器内核#xff0c;还可以通过Cef暴露出来的各种Handler来实现我们自己的资源请求处理。什么是资源请求呢#xff1f;简单来说#xff0c;就是前端页面在加载的过程中#xff0c;请求的各种文本#xff08;js、cs…前言在CefSharp中我们不仅可以使用Chromium浏览器内核还可以通过Cef暴露出来的各种Handler来实现我们自己的资源请求处理。什么是资源请求呢简单来说就是前端页面在加载的过程中请求的各种文本js、css以及html。在以Chromium内核的浏览器上我们可以使用浏览器为我们提供的开发者工具来检查每一次页面加载发生的请求。准备鉴于本文的重心是了解CefSharp的资源拦截处理所以我们不讨论前端的开发以及客户端嵌入CefSharp组件的细节。我们首先完成一个基本的嵌入CefSharp的WinForm程序该程序界面如下拥有一个地址输入栏和一个显示网页的Panel并且编写一个极其简单的页面该页面会请求1个js资源和1个css资源demo:- index.html- test1.js- test1.css这几个文件的代码都十分简单body {background-color: aqua } function myFunc() {return test1 js file; } !DOCTYPE html html langen xmlnshttp://www.w3.org/1999/xhtml headmeta charsetutf-8 /titleHome/title!-- 如下记载js、css资源 --script typetext/javascript srctest1.js/scriptlink typetext/css relstylesheet hreftest1.css/ /head body h1Resource Intercept Example/h1 h2 idresult/h2 script// 调用test1.js中的myFuncdocument.getElementById(result).innerHTML myFunc(); /script /body /html代码很简单效果也很容易知道页面加载后页面背景色为aqua页面上会显示文本“test1 js file”。同时当我们使用开发工具刷新页面能够看到对应的资源加载CefSharp资源拦截及自定义处理完成上述准备后我们进入正文资源拦截及自定义处理。首先我们需要对目标的理解达成一致资源拦截是指我们能够检测到上图中的html、js还有css的资源请求事件在接下来的Example中因为我们是使用的客户端程序所以会在请求的过程中弹出提示自定义处理是指在完成拦截提示后我们还能够替换这些资源这里我们设定完成拦截后可以把js和css换为我们想要另外的文件test2.js和test2.cssfunction myFunc() {return test2 js file; } body {background-color: beige } 即我们希望拦截并替换后页面上的文字不再是之前的而是“test2 js file”页面的背景色是beige。IRequestHandler在CefSharp中要想对请求进行拦截处理最为核心的Handler就是IRequestHandler这个接口查看官方的源码会发现里面有数个方法的定义通过阅读官方的summary我们可以聚焦到如下的两个定义注释本人进行了删减/// summary /// Called before browser navigation. /// 译在浏览器导航前调用 /// If the navigation is allowed see crefE:CefSharp.IWebBrowser.FrameLoadStart / and see crefE:CefSharp.IWebBrowser.FrameLoadEnd / /// will be called. If the navigation is canceled see crefE:CefSharp.IWebBrowser.LoadError / will be called with an ErrorCode /// value of see crefF:CefSharp.CefErrorCode.Aborted /. /// /summary bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser,IBrowser browser,IFrame frame,IRequest request,bool userGesture,bool isRedirect);/// summary /// Called on the CEF IO thread before a resource request is initiated. /// 在一个资源请求初始化前在CEF IO线程上调用 /// /summary IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser,IBrowser browser,IFrame frame,IRequest request,bool isNavigation,bool isDownload,string requestInitiator,ref bool disableDefaultHandling); 于是我们继承一个默认的名为RequestHandler的类请区分DefaultRequestHandler只重写上述的两个方法。public class MyRequestHandler : RequestHandler{protected override bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture,bool isRedirect){// 先调用基类的实现断点调试return base.OnBeforeBrowse(chromiumWebBrowser, browser, frame, request, userGesture, isRedirect);}protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame,IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling){// 先调用基类的实现断点调试return base.GetResourceRequestHandler(chromiumWebBrowser, browser, frame, request, isNavigation, isDownload, requestInitiator, ref disableDefaultHandling);}} 然后完成对该Handler的注册this._webBrowser new ChromiumWebBrowser(string.Empty){RequestHandler new MyRequestHandler()}; 打上断点开始访问我们的Exampleindex.html。这里会发现OnBeforeBrowse调用了一次而GetResourceRequestHandler会调用3次。检查OnBeforeBrowse中的request参数内容是一次主页的请求而GetResourceRequestHandler中的3次分别是主页html资源、test1.js和test1.css。结合官方注释和调试的结果我们可以得出结论要进行导航的拦截我们可以重写OnBeforeBrowse方法要想进行资源的拦截我们需要实现自己的ResourceRequestHandler。IResourceRequestHandler查看IResourceRequestHandler的定义我们再次聚焦一个函数定义/// summary /// Called on the CEF IO thread before a resource is loaded. To specify a handler for the resource return a see crefT:CefSharp.IResourceHandler / object /// /summary /// returnsTo allow the resource to load using the default network loader return null otherwise return an instance of see crefT:CefSharp.IResourceHandler / with a valid stream/returns IResourceHandler GetResourceHandler(IWebBrowser chromiumWebBrowser,IBrowser browser,IFrame frame,IRequest request); 该定义从注释可以看出如果实现返回null那么Cef会使用默认的网络加载器来发起请求或者我们可以返回一个自定义的资源处理器ResourceHandler来处理一个合法的数据流Stream。也就是说对于资源的处理要想实现自定义的处理不是拦截拦截到目前为止我们可以在上述的两个Handler中进行处理我们还需要实现一个IResourceHandler接口的实例并在GetResourceHandler处进行返回Cef才会在进行处理的时候使用我们的Handler。所以在GetResourceHandler中我们进行资源的判断如果是想要替换的资源我们就使用WinForm提供的OpenFileDialog来选择本地的js或是css文件并传给我们自定义的ResourceHandler如果不是想要拦截的资源或是用户未选择任何的文件就走默认的public class MyResourceRequestHandler : ResourceRequestHandler {protected override IResourceHandler GetResourceHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request){if (request.Url.EndsWith(test1.js) || request.Url.EndsWith(test1.css)){MessageBox.Show($资源拦截{request.Url});string type request.Url.EndsWith(.js) ? js : css; // 这里简单判断js还是css不过多编写string fileName null;using (OpenFileDialog openFileDialog new OpenFileDialog()){openFileDialog.Filter ${type}文件|*.{type}; // 过滤openFileDialog.Multiselect true;if (openFileDialog.ShowDialog() DialogResult.OK){fileName openFileDialog.FileName;}}if (string.IsNullOrWhiteSpace(fileName)){// 没有选择文件还是走默认的Handlerreturn base.GetResourceHandler(chromiumWebBrowser, browser, frame, request);}// 否则使用选择的资源返回return new MyResourceHandler(fileName);}return base.GetResourceHandler(chromiumWebBrowser, browser, frame, request);} } IResourceHandler根据上文我们进一步探究IResourceHandler对该Handler官方有一个默认的实现RequestHandler该Handler通过阅读源码可以知道是网络加载的Handler这里为了实现我们自定义拦截策略我们最好单独实现自己的IResourceHandler。对于该接口有如下的注释/// summary /// Class used to implement a custom resource handler. The methods of this class will always be called on the CEF IO thread. /// Blocking the CEF IO thread will adversely affect browser performance. We suggest you execute your code in a Task (or similar). /// To implement async handling, spawn a new Task (or similar), keep a reference to the callback. When you have a /// fully populated stream, execute the callback. Once the callback Executes, GetResponseHeaders will be called where you /// can modify the response including headers, or even redirect to a new Url. Set your responseLength and headers /// Populate the dataOut stream in ReadResponse. For those looking for a sample implementation or upgrading from /// a previous version see crefT:CefSharp.ResourceHandler /. For those upgrading, inherit from ResourceHandler instead of IResourceHandler /// add the override keywoard to existing methods e.g. ProcessRequestAsync. /// /summary public interface IResourceHandler : IDisposable { ... } 该类的注释意思大致为我们可以通过实现该接口来实现自定义资源的处理类。该类中的方法总是在CEF的IO线程中调用。然而阻塞CEF IO线程将会不利于浏览器的性能。所以官方建议开发者通过把自己的处理代码放在Task或是类似的异步编程框架中异步执行然后在完成或取消失败时在异步中调用callback对应的操作函数continue、cancel等方法。当你拥有一个完全填充fully populated好了的Stream的时候再执行callback这一步对应Open方法。一旦callback执行了GetResponseHeaders这个方法将会调用于是你可以在这个方法里面对Reponse的内容包括headers进行修改或者甚至是重定向到一个新的Url。设置你自己的reponseLength和headers。接下来通过在ReadResponse实际上即将作废而是Read函数中实现并填充dataOut这个Stream。最终CEF会对该Stream进行读取数据获得资源数据。事实上该Handler的实现可以有很多花样这里我们实现一个最简单的。Dispose对于通常进行资源释放的Dispose因为我们这里只是一个Demo所以暂时留空。OpenProcessRequest官方注释指出ProcessRequest将会在不久的将来弃用改为Open。所以ProcessRequest我们直接返回true。对于Open方法其注释告诉我们要想要立刻进行资源处理同步请设置handleRequest参数为true并返回true决定稍后再进行资源的处理异步设置handleRequest为false并调用callback对应的continue和cancel方法来让请求处理继续还是取消并且当前Open返回false。要立刻取消资源的处理设置handleRequest为true并返回false。也就是说handleRequest的true或false决定是同步还是异步处理。若同步则Cef会立刻通过Open的返回值true或false来决定后续继续进行还是取消。若为异步则Cef会通过异步的方式来检查callback的调用情况这里的callback实际上是要我们创建Task回调触发的。这里我们选择同步的方式选择异步也没有问题编写如下的代码public bool Open(IRequest request, out bool handleRequest, ICallback callback) {handleRequest true;return true; } GetResponseHeaders在上小节中我们已经完成了对资源数据的入口Open的分析。既然我们已经告诉了Cef我们准备开始进行资源请求的处理了那么接下来我们显然需要着手进行资源的处理。根据前面的概要注释我们需要实现GetResponseHeaders方法因为这是资源处理的第二步。该方法的注释如下/// summary /// Retrieve response header information. If the response length is not known /// set paramref nameresponseLength / to -1 and ReadResponse() will be called until it /// returns false. If the response length is known set paramref nameresponseLength / /// to a positive value and ReadResponse() will be called until it returns /// false or the specified number of bytes have been read. /// /// It is also possible to set paramref nameresponse / to a redirect http status code /// and pass the new URL via a Location header. Likewise with paramref nameredirectUrl / it /// is valid to set a relative or fully qualified URL as the Location header /// value. If an error occured while setting up the request you can call /// see crefP:CefSharp.IResponse.ErrorCode / on paramref nameresponse / to indicate the error condition. /// /summary void GetResponseHeaders(IResponse response, out long responseLength, out string redirectUrl); Summary翻译解释如下获取响应头信息。如果响应的数据长度未知则设置responseLength为-1然后CEF会一直调用ReadResponse即将废除实际上是Read方法直到该Read方法返回false。如果响应数据的长度是已知的可以直接设置responseLength长度为一个正数然后ReadResponseRead将会一直调用直到该Read方法返回false或者在已经读取的数据的字节长度达到了设置的responseLength的值。当然你也可以通过设置response.StatusCode值为重定向的值30x以及redirectUrl为对应的重定向Url来实现资源重定向。在本文中我们采取简单的方式直接返回资源的长度然后交给下一步的Read方法来进行真正的资源处理。在该步骤中我们编写获取本地文件字节数据来实现js和css文件的本地加载并且将该数据保存在该ResourceHanlder实例私有变量中。public void GetResponseHeaders(IResponse response, out long responseLength, out string redirectUrl) {using (FileStream fileStream new FileStream(this._localResourceFileName, FileMode.Open, FileAccess.Read)){using (BinaryReader binaryReader new BinaryReader(fileStream)){long length fileStream.Length;this._localResourceData new byte[length];// 读取文件中的内容并保存到私有变量字节数组中binaryReader.Read(this._localResourceData, 0, this._localResourceData.Length);}}responseLength this._localResourceData.LongLength;redirectUrl null; } Read该方法的定义和注释如下/// summary /// Read response data. If data is available immediately copy up to /// dataOut.Length bytes into dataOut, set bytesRead to the number of /// bytes copied, and return true. To read the data at a later time keep a /// pointer to dataOut, set bytesRead to 0, return true and execute /// callback when the data is available (dataOut will remain valid until /// the callback is executed). To indicate response completion set bytesRead /// to 0 and return false. To indicate failure set bytesRead to lt; 0 (e.g. -2 /// for ERR_FAILED) and return false. This method will be called in sequence /// but not from a dedicated thread. /// /// For backwards compatibility set bytesRead to -1 and return false and the ReadResponse method will be called. /// /summary bool Read(Stream dataOut, out int bytesRead, IResourceReadCallback callback); Summary的翻译大致为读取响应数据。如果数据是可以立即获得的那么可以直接将dataOut.Length长度的字节数据拷贝到dataOut这个流中然后设置bytesRead的值为拷贝的数据字节长度值最后再返回true。如果开发者希望继续持有dataOut的引用注释是pointer指针但是个人觉得这里写为指向该dataOut的引用更好然后在稍后填充该数据流那么可以设置bytesRead为0通过异步方式在数据准备好的时候执行callback的操作函数然后立刻返回true。dataOut这个流会一直保持不被释放直到callback被调用为止。为了让CEF知道当前的响应数据已经填充完毕需要设置bytesRead为0然后返回false。要想让CEF知道响应失败需要设置bytesRead为一个小于零的数例如ERR_FAILED: -2然后返回false。这个方法将会依次调用但不是在一个专有线程。根据上述的注释总结如下bytesRead 0return true填充了数据但Read还会被调用bytesRead 0return false数据填充完毕当前为最后一次调用bytesRead 0return false出错当前为最后一次调用bytesRead 0return trueCEF不会释放dataOut流在异步调用中准备好数据后调用callback针对本例我们增加一个该类的私有变量_dataReadCount用于标识已读的资源数据字节量并在构造函数中初始化为0。每次在Read中进行读取的时候首先检查剩余待读取字节数this._localResourceData.LongLength - this._dataReadCount如果该值为零则表明已经将所有的数据通过dataOut拷贝给了外围此时设置bytesRead为0直接返回false若剩余值大于0则需要继续进行拷贝操作但需要注意的是dataOut并不是一个无限大的流而是一个类似于缓存的流它的Length值为2^16 65536所以我们需要设置bytesRead来让外围知道我们实际在这个流中放了多少字节的数据。同时在使用Stream.WriteAPI的时候需要设置正确的offset和count。最终Read的实现如下public bool Read(Stream dataOut, out int bytesRead, IResourceReadCallback callback) {int leftToRead this._localResourceData.Length - this._dataReadCount;if (leftToRead 0){bytesRead 0;return false;}int needRead Math.Min((int)dataOut.Length, leftToRead); // 最大为dataOut.LenghtdataOut.Write(this._localResourceData, this._dataReadCount, needRead);this._dataReadCount needRead;bytesRead needRead;return true; } 其他的几个方法对于Cancel和Skip方法在本例不会调用所以这里使用默认实现不进行讨论感兴趣的伙伴可以自己去研究。最终效果通过上文的代码设计和编写我们最终完成了一个简单的资源拦截及自定义处理的Example。首先我们在不进行资源拦截的情况下加载我们的web页面可以看到界面中呈现“test1 js file”的字样以及背景色为海蓝色。接下来我们开启资源拦截再次加载页面在加载过程中会有对应资源的拦截时的弹窗以及我们需要选择我们自定义的资源文件拦截到JS手动更改加载的JS拦截到CSS手动更改加载的CSS完成处理后得到如下的显示页面源码本Example的源码已经开源在Github上整个Demo较为简单主要是对本文的验证CefSharpResourceInterceptExample​github.com
http://www.pierceye.com/news/277015/

相关文章:

  • 青岛建设集团招聘信息网站公司官网怎么制作
  • 本溪网站开发公司电话县蒙文网站建设汇报
  • 广州建网站有哪些怎么做网站建设赚钱
  • led视频网站建设邯郸建设信息网站
  • 开发网站培训班网站详情页用cdr做可以吗
  • 相亲网站开发与设计报告广州网站维护
  • 门户网站 技术方案北京感染人数最新消息
  • 网站制作过程流程酷家乐在线设计官网
  • 六年级做网站的软件小程序开发文档微信小程序
  • 做网站要准备哪些汕头建站公司模板
  • 杭州多语言网站建设网站转app工具
  • 一流的网站建设wordpress 读者墙
  • php 视频播放网站开发php做直播类型的网站
  • 网站建设氺金手指排名11wordpress手机端菜单
  • 存储网站建设软件界面设计图
  • 微信 公司网站 怎么做WordPress安装在Windows
  • 商丘给企业做网站的公司已备案域名租用
  • .net商城网站模板下载网站开发怎么对接客户
  • php程序员网站开发域名企业备案对网站的好处
  • 沈阳市城乡建设网站wordpress全文
  • 冉冉科技网站建设网络教学平台网址
  • 深圳网站设计建设公司宁波易通建设网站
  • 许昌网站建设公司网站的空间和域名
  • 公司查询网站查询系统wordpress简书主题
  • 公司网站 钓鱼网站ui设计交付物都包含哪些
  • seo网站导航建设技巧精东影视传媒文化管理公司
  • 做白酒的网站怎么查网站建设是哪家公司
  • 网站域名密码免费网站推广产品
  • 网站建设一般要多少费用申请网站官网
  • 金融网站织梦模板二手车网站建设