一、前言

忙里偷闲,研究了一下如何在CEF中拦截请求,并作出响应。这个功能对某些需要修改服务器响应的需求来说必不可少,可以直接读取本地文件作为响应内容。

C#的CEF封装项目有很多,我使用的是ChromiumFx。它的最大特点是采用事件的形式实现接口的效果。这样我们在使用时只需要订阅事件实现功能即可,而不用继承类重写方法,这很苏胡。

二、CEF3接口

简单介绍一下CEF3的接口。

CefClient:回调管理类,包含5个接口用于创建其它的回调类的对象

CefLifeSpanHandler: 回调类,用于控制popup对话框的创建和关闭等操作

CefLoadHandler: 回调类,可以用来监听frame的加载开始,完成,错误等信息

CefRequestHandler: 回调类,用于监听资源加载,重定向等信息

CefDisplayHandler: 回调类,用于监听页面加载状态,地址变化,标题等得信息

CefGeolocationHandler: 回调类,用于CEF3向嵌入者申请geolocation的权限 CefApp: 与进程,命令行参数,代理,资源管理相关的回调类,用于让CEF3的调用者们定制自己的逻辑

CefBrowser: renderer进程中执行浏览相关的类,例如前进,后退等

CefBrowserHost: browser进程中的执行浏览相关的类,其会把请求发送给CefBrowser

CefFrame: 表示的是页面中的一个Frame,可以加载特定url,在该运行环境下执行JavaScript代码等得。

V8:CEF3提供支持V8extension的接口,但是这有两个限制,第一,v8 extension仅在Renderer进程使用;第二,仅在沙箱模型关闭时使用。

三、流程

我们关注的就是上述的CefRequestHandler接口,其中包含了发起请求,读取响应结果的接口方法。

以下内容在ChromiumFx库上实现,使用其它库大致相似。

1. ChromiumWebBrowser提供了RequestHandler类,在GetResourceHandler中可以根据需要指定ResourceHandler实例以实现拦截响应请求,或返回null来使用cef默认的方式处理请求。

2.新建ResourceHandler实例,并指定以下事件发生时的动作:

ProcessRequest 处理请求,允许请求返回true;取消请求返回false。当需要返回的数据就绪后(自行请求网络或者文件就绪)或立即调用callback.Continue(),通知cef进入下一步:GetResponseHeaders。

GetResponseHeaders 设置响应头,在这里可以设置mime-type,响应长度,其它头等。不确定长度设置响应长度为-1。

ReadResponse 设置响应结果。可以设置响应具体内容,设置已读取长度。cef调用完上一步后会继续调用此方法。根据响应长度和数据就绪情况,调用此方法的次数和策略不同。

当响应长度为-1时,cef无法根据已读长度确定是否已读取完毕,必需根据返回值false来结束读取。

当响应长度大于0时,cef根据每次调用得到的已读长度,或返回值false来结束读取。

如果数据未就绪,可以设置读取长度为0 ,返回true,并在稍后调用callbak.Continue()通知cef调用此方法读取响应内容。

注意:

当响应长度为-1时,必需保证此方法至少执行两次,第一次返回true表示数据全部就绪,第二次返回false表示读取结束。

当响应长度大于0时,设置内容和已读长度,返回true。则此方法只执行一次。

若实际返回的响应内容,长度大于之前设置的响应总长度,则返回内容将被截取。

四、代码

其中还包括了其它设置和订阅了一些有趣的事件,供参考。

    public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitializationChromium();
} private void InitializationChromium()
{
ChromiumWebBrowser.OnBeforeCfxInitialize += ChromiumWebBrowser_OnBeforeCfxInitialize;
ChromiumWebBrowser.OnBeforeCommandLineProcessing += ChromiumWebBrowser_OnBeforeCommandLineProcessing;
ChromiumWebBrowser.Initialize(); ChromiumWebBrowser wb = new ChromiumWebBrowser();
wb.Dock = DockStyle.Fill;
wb.Parent = this;
wb.LoadHandler.OnLoadStart += LoadHandler_OnLoadStart;
wb.LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd;
wb.DownloadHandler.OnBeforeDownload += DownloadHandler_OnBeforeDownload;
wb.RequestHandler.OnBeforeBrowse += RequestHandler_OnBeforeBrowse;
wb.RequestHandler.GetResourceHandler += RequestHandler_GetResourceHandler;
wb.SetWebResource("http://localresource/html", new Chromium.WebBrowser.WebResource("<html></html>"));
wb.LoadUrl("http://m.baidu.com");
} void RequestHandler_GetResourceHandler(object sender, Chromium.Event.CfxGetResourceHandlerEventArgs e)
{
if (e.Request.Url == "http://m.baidu.com/")
{
CfxResourceHandler handler = new CfxResourceHandler();
handler.ProcessRequest += handler_ProcessRequest;
handler.GetResponseHeaders += handler_GetResponseHeaders;
handler.ReadResponse += handler_ReadResponse; e.SetReturnValue(handler);
}
else
{
e.SetReturnValue(null);
}
} void handler_ProcessRequest(object sender, Chromium.Event.CfxProcessRequestEventArgs e)
{
e.Callback.Continue();
e.SetReturnValue(true);
} void handler_GetResponseHeaders(object sender, Chromium.Event.CfxGetResponseHeadersEventArgs e)
{
e.ResponseLength = -1;
e.Response.MimeType = "text/html";
e.Response.Status = 200;
} int count = 0;
void handler_ReadResponse(object sender, Chromium.Event.CfxReadResponseEventArgs e)
{
if (count == 0)
{
byte[] data = Encoding.UTF8.GetBytes("<html><body><h1>Hello CEF</h1></body></html>");
e.BytesRead = data.Length;
Marshal.Copy(data, 0, e.DataOut, data.Length);
e.SetReturnValue(true);
count++;
}
else
{
e.SetReturnValue(false);
}
} void RequestHandler_OnBeforeBrowse(object sender, Chromium.Event.CfxOnBeforeBrowseEventArgs e)
{
if (e.Request.Url == "")
{
e.SetReturnValue(true);
}
} void DownloadHandler_OnBeforeDownload(object sender, Chromium.Event.CfxOnBeforeDownloadEventArgs e)
{
e.Callback.Continue("d:\\" + e.SuggestedName, false);
} void LoadHandler_OnLoadEnd(object sender, Chromium.Event.CfxOnLoadEndEventArgs e)
{
//MessageBox.Show("end loading" + e.Frame.Url);
//MessageBox.Show("is main:" + e.Frame.IsMain);
e.Frame.SelectAll();
} void LoadHandler_OnLoadStart(object sender, Chromium.Event.CfxOnLoadStartEventArgs e)
{
//MessageBox.Show("start loading"+e.Frame.Url);
} void ChromiumWebBrowser_OnBeforeCommandLineProcessing(Chromium.Event.CfxOnBeforeCommandLineProcessingEventArgs e)
{
e.CommandLine.AppendSwitch("--disable-web-security");
} void ChromiumWebBrowser_OnBeforeCfxInitialize(Chromium.WebBrowser.Event.OnBeforeCfxInitializeEventArgs e)
{
e.Settings.CachePath = "Session";
e.Settings.Locale = "zh-CN";
} private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
CfxRuntime.Shutdown();
}
}

响应长度已知的情况:

         void handler_GetResponseHeaders(object sender, Chromium.Event.CfxGetResponseHeadersEventArgs e)
{
e.ResponseLength = Encoding.UTF8.GetBytes("<html><body><h1>Hello CEF</h1></body></html>").Length;
e.Response.MimeType = "text/html";
e.Response.Status = ;
} void handler_ReadResponse(object sender, Chromium.Event.CfxReadResponseEventArgs e)
{
byte[] data = Encoding.UTF8.GetBytes("<html><body><h1>Hello CEF</h1></body></html>");
e.BytesRead = data.Length;
Marshal.Copy(data, , e.DataOut, data.Length);
e.SetReturnValue(true);
}

最终效果如下:

综上所述,虽然学到了新知识,但女朋友不理你还是开心不起来对吧。

五、参考资料

https://groups.google.com/forum/#!topic/cefglue/k-ixiAiszYg

https://code.google.com/p/cefpython/source/browse/cefpython/cef3/linux/binaries_64bit/wxpython-response.py?r=26d373f81ca9

http://blog.csdn.net/lee353086/article/details/40779471

使用C#在CEF中拦截并响应请求的更多相关文章

  1. Structs2 中拦截器获取请求参数

    前言 环境:window 10,JDK 1.7,Tomcat 7 测试代码 package com.szxy.interceptor; import java.util.Map; import jav ...

  2. 说说struts2中拦截器的请求流程一(模拟大致流程)

    本文可作为北京尚学堂struts2课程的学习笔记. 首先 什么是拦截器?拦截器能干什么? 拦截器,顾名思义就是拦截对象然后做操作的东西,至于是拦截谁?那自然是拦截action了.能做什么操作呢?你想让 ...

  3. 简单理解Struts2中拦截器与过滤器的区别及执行顺序

    简单理解Struts2中拦截器与过滤器的区别及执行顺序 当接收到一个httprequest , a) 当外部的httpservletrequest到来时 b) 初始到了servlet容器 传递给一个标 ...

  4. Mock.js开发中拦截Ajax

    Mock.js 是一款前端开发中拦截Ajax请求再生成随机数据响应的工具.可以用来模拟服务器响应. 优点是非常简单方便, 无侵入性, 基本覆盖常用的接口数据类型. 在我们的生产实际中,后端的接口往往是 ...

  5. vue中采用axios发送请求及拦截器

    这几天在使用vue中axios发送get请求的时候很顺手,但是在发送post请求的时候老是在成功的回调函数里边返回参数不存在,当时就纳闷了,经过查阅资料,终于得到了解决方案,在此做一总结: 首先我们在 ...

  6. Fragment中onActivityResult不响应

    开发中遇到Fragment中onActivityResult不响应的问题,曾经见过. 不少同学说处理方法是在与Fragment绑定的FragmentActivity中重写onActivityResul ...

  7. Spring 中拦截器与过滤器的区别

    spring 中拦截器 与servlet 的filter 有相似之处.比如二者都是aop 编程思想的体现都能实现权限检查,日志记录等. 不同之处 使用范围不同 Filter 是Servlet 规定的. ...

  8. axios设置请求拦截和响应拦截

    首先我们先创建axios实例 const service = axios.create({ baseURL: url, //是用于请求的服务器 URL timeout: 5000, // 请求超时时间 ...

  9. shiro中拦截器机制

    8.1 拦截器介绍 Shiro使用了与Servlet一样的Filter接口进行扩展:所以如果对Filter不熟悉可以参考<Servlet3.1规范>http://www.iteye.com ...

随机推荐

  1. 【Unity3d】火炬之光的X射线效果

    http://www.cnblogs.com/dosomething/archive/2012/04/03/2431149.html 人物和摄像机之间存在例如墙壁等的阻挡时  可以修改阻挡材质的alp ...

  2. 跟着百度学PHP[5]函数篇2-PHP中的特殊形式的函数

    目录...................................................... .00x1 可变函数 在PHP里面如果说将“函数名称”赋予字符串类型的变量.在调用这个 ...

  3. git+github上传与管理

    1.首先下载并安装git,方便管理github上的代码 https://git-scm.com/downloads 2.然后点击安装好的git bash(注册好自己的github) git confi ...

  4. 在WPF中使用WinForm控件方法

    1.      首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll. 2.      在要使用WinForm控 ...

  5. sgu 240 Runaway (spfa)

    题意:N点M边的无向图,边上有线性不下降的温度,给固定入口S,有E个出口.逃出去,使最大承受温度最小.输出该温度,若该温度超过H,输出-1. 羞涩的题意 显然N*H的复杂度dp[n][h]表示到达n最 ...

  6. sqlserver添加主键

    sqlServer中给表添加主键的sql: alter table market_media_medical_history alter column pk_id bigint not null; a ...

  7. ProtocolBuffers-3 For Objective C (1)-简单的使用

    一. 介绍 Protocolbuffer 是一种数据交换格式,类似于我们现在使用的XML和JSON.是Google公司推出的,本来这个语言是Google公司内部使用的,随着Google对这个格式的优化 ...

  8. CString转换为string

    string CStringToString(CString strMFC) { CStringA strA; strA = strMFC.GetBuffer(); strMFC.ReleaseBuf ...

  9. mvc架构

    mvc是三个单词的缩写,他们是Model(模型),view(视图),controller(控制) 1)最上面的一层,是直接面向最终用户的"视图层"(View).它是提供给用户的操作 ...

  10. runtime运行时

    /** * Describes the instance variables declared by a class. * * @param cls The class to inspect. * @ ...